Functions with const arguments and Overloading

10,110

Solution 1

You can't overload based only on the constness of a non pointer, non reference type.

Think for instance if you were the compiler. Faced with the line:

 cout <<obj.foo(3);

which function would you call?

As you are passing by value the value gets copied either way. The const on the argument is only relevant to the function definition.

Solution 2

§13.1 where the Standard discusses about declarations that cannot be overloaded states -

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored [...]

Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations. [...]

when determining which function is being declared, defined, or called. "In particular, for any type T, “pointer to T,” “pointer to const T,” and “pointer to volatile T” are considered distinct parameter types, as are “reference to T,” “reference to const T,” and “reference to volatile T.”

EDIT 2:

As the post is essentially the same as the reffered post, except that the overloaded functions are now class member functions, I am trying to illustrate an additional aspect that could be useful to illustrate the concept of overloading which is not the same as overloading based on the 'constness' of the arguments (either in class scope or namespace scope). However the OP wanted to know how to differentiate the two overloads.

A way to overload them successfully relies on the cv qualification of the implied first parameter in case of member function calls as shown. The 'const' member function can only be called when the object expression used to invoke the overloaded member function is also a const. When a non const object expression is used to invoke the overloaded member function call, the non const version is preferred as it is an exact match (the call to const member function overload will require cv qualification of the first implied argument)

#include <iostream> 
using std::cout; 

class Test { 
        public: 
        Test(){}
        int foo (const int) const; 
        int foo (int ); 
}; 

int main () 
{ 
        Test obj;
        Test const objc;  // const object
        obj.foo(3);       // calls non const overload, object expression obj is non const
        objc.foo(3);      // calls const overload, object expression objc is const
} 

int Test::foo(int a) 
{ 
   a++; 
   return a; 
} 

int Test::foo (const int a) const
{ 
   return a; 
} 

Solution 3

As the answer to the other question explains, the two foos do not differ because they have equivalent parameter definitions.

Share:
10,110
Sii
Author by

Sii

Updated on June 04, 2022

Comments

  • Sii
    Sii almost 2 years

    Was tryin out the stackeroverflow qn so it got me thinking why not overload the the function and I came up with a slightly different code but it says the function cannot be overloaded. My question is why? or is there a another way?

     #include <iostream>
     using std::cout;
    
     class Test {
             public:
             Test(){ }
             int foo (const int) const;
             int foo (int );
     };
    
     int main ()
     {
             Test obj;
             Test const obj1;
             int variable=0;
         do{
             obj.foo(3);        // Call the const function 
              obj.foo(variable); // Want to make it call the non const function 
             variable++;
                 usleep (2000000);
            }while(1);
     }
    
     int Test::foo(int a)
     {
        cout<<"NON CONST"<<std::endl;
        a++;
        return a;
     }
    
     int Test::foo (const int a) const
     {
        cout<<"CONST"<<std::endl;
        return a;
     }
    
    • Maciej Hehl
      Maciej Hehl over 13 years
      What do you mean by "it says the function cannot be overloaded". Do you get a compilation error? What error? Or is it just the behaviour, that says it? If it's the behaviour, then your conclusion is wrong, I'm afraid. You actually overloaded successfully. The problem is, that the resolution is made based on a different thing, you think it should be.
    • Sii
      Sii over 13 years
      @Maciej..yeah that was a compilation error..i have passed that point..Check out the follow up thread...stackoverflow.com/questions/3683881/…
  • James McNellis
    James McNellis over 13 years
    Heh. I like that the standard uses the extremely technical term, "buried," to describe non-top-level cv-qualifiers. :-P
  • Sii
    Sii over 13 years
    my idea was to make it call the foo (const int a) function..So hence my real question how would you make it call the const function( and also make it compilable)
  • Sii
    Sii over 13 years
    I did see the standards mentioned in the linked thread..hence the question 'or is there a another way?' to make the it call the const function
  • Dominique McDonnell
    Dominique McDonnell over 13 years
    @MrProg: As stated, the language doesn't support it. If you really to do that, do something like foo(const int&) and foo(int&). This will do what you want, though the non const version will be able to change the variable passed in.
  • Chubsdad
    Chubsdad over 13 years
    @MrProg: Sorry, my oversight on your second question. Have tried to answer that in EDIT2
  • Sii
    Sii over 13 years
    I dont know which compiler you are using ..i am using gnu g++..it calls the non const version both the times.
  • Chubsdad
    Chubsdad over 13 years
    @MrProg: There was an error in declaring 'objc'. Please check now.
  • Sii
    Sii over 13 years
    Ahh..this give me a much better idea. but if you pass a non const value I mean something like int j (which isnt const int )...objc.foo(j) should call the non const function but it doesnt
  • James McNellis
    James McNellis over 13 years
    I am confused. The const qualification of the member function has no relation to the const qualification of the int parameter. They are completely unrelated.
  • Chubsdad
    Chubsdad over 13 years
    @James McNellis: Yes. That's true. But this post is about moving the code from the link referred in OP from namespace into a class. All the points discussed there are still valid here as MrProg confirmed above. Hence I tried to illustrate the overloading based on cv qualification of the implied parameter
  • Chubsdad
    Chubsdad over 13 years
    @MrProg: No. Even if the 'const member function' has a non const parameter, it will be called if the calling object expression is const.
  • Chubsdad
    Chubsdad over 13 years
    @James McNellis: If this is confusing, I am all for deleting this post.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas over 13 years
    @MrProg: I guess the quote from the standard is not clear. It basically means that void foo(int); and void foo(const int) are the same signature, in both cases the argument will be copied and the caller integer will not be modified. The difference in const there only affects the definition of the function, where in the second case the definition cannot modify its own copy of the value.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas over 13 years
    @MrProg: Overloading on the const-ness of the member method itself is allowed in the same way that overloading on the const-ness of the pointed type in a pointer parameter: void foo( int * p ); void foo( const int * ); But the difference is the const-ness of the implicit this, not the argument. To make it call the const version, use a const reference to the object: const_cast<const T &>(o).f(5); will call the const version, while const_cast<T&>(o).f(5) will call the non-const, independently of the argument to the method
  • David Rodríguez - dribeas
    David Rodríguez - dribeas over 13 years
    @MrProg: if for some obscure reason you want int x; const int y; f(x); f(y); to call different functions (even if in neither case the function will modify x or y, you could use references: void f( int & x ); void f( const int & y ); but that will allow the first version to modify the x that is passed as argument, and thus is not semantically equivalent to your initial code. I really cannot see a use case where you would want to pass by value and still call different overloads if the argument was const/non-const.
  • Johannes Schaub - litb
    Johannes Schaub - litb over 13 years
    @James since the quoted text is all a big non-normative note, using "buried" isn't quite surprising :)
  • user3665224
    user3665224 over 8 years
    +1 for stating "constness of non pointer, non reference type". A function can be overloaded on the constness of pointer and reference type.
  • JAB
    JAB over 8 years
    @user3665224 The constness of the pointer type or the type it points to? (e.g. const int */int const * versus int * const)