views:

142

answers:

3

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;
 }
+8  A: 

§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; 
} 
Chubsdad
@Chubsdad: Beat me to it
DominicMcDonnell
Heh. I like that the standard uses the extremely technical term, "buried," to describe non-top-level cv-qualifiers. :-P
James McNellis
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
Sii
@MrProg: Sorry, my oversight on your second question. Have tried to answer that in EDIT2
Chubsdad
I dont know which compiler you are using ..i am using gnu g++..it calls the non const version both the times.
Sii
@MrProg: There was an error in declaring 'objc'. Please check now.
Chubsdad
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
Sii
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.
James McNellis
@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
@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
@James McNellis: If this is confusing, I am all for deleting this post.
Chubsdad
@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
@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
David Rodríguez - dribeas
@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 void f( const int ` 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.
David Rodríguez - dribeas
@James since the quoted text is all a big non-normative note, using "buried" isn't quite surprising :)
Johannes Schaub - litb
+9  A: 

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.

DominicMcDonnell
+1: Nice explanation
Chubsdad
+1 for providing not just rules, but insight behind them.
Tony
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
DominicMcDonnell
+1  A: 

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

jwfearn