1

This is a follow up of the Previous Question

It got really complicated so I am starting a new thread to make my point clearer.( Didnt want to delete the previous thread because the other guys who gave valuable feedback dont not loose the reputation points they gained)

Updated Code: (Complies and Works)

#include <iostream>
 using std::cout;

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

 int main ()
 {   
         Test obj;
         int variable=0;  
         int output;
     do{ 
         output=obj.foo(3);        // Call the const function 
         cout<<"output::"<<output<<std::endl;
         output=obj.foo(variable); // Want to make it call the non const function 
         cout<<"output::"<<output<<std::endl;
         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;
 }   

Output (I get):

NON CONST
output::4
NON CONST
output::1
NON CONST
output::4
NON CONST
output::2
NON CONST
output::4
NON CONST
output::3
NON CONST
output::4
NON CONST
output::4
NON CONST
output::4
NON CONST
output::5

Output (I desired/had in mind)

CONST
output::3
NON CONST
output::1
CONST
output::3
NON CONST
output::2
CONST
output::3
NON CONST
output::3
CONST
output::3
NON CONST
output::4
CONST
output::3
NON CONST
output::5

Hope I have presented my question better. I know other ways to do it. but is this possible.

Community
  • 1
  • 1
Sii
  • 661
  • 2
  • 7
  • 16
  • Hmm, that's the first time I've seen any one use a do-while in practical code. – Alexander Rafferty Sep 10 '10 at 10:35
  • dont know if this is practical or not..i took it up as a brain teasor and trying to get my head round it..what other way to learn than get our hands dirty ;) – Sii Sep 10 '10 at 10:41
  • I don't understand how this isn't a duplicate of your previous question. As `int foo(int);` and `int foo(const int);` are the same function signatures your question would be clearer if you used the two signatures `int foo(int);` and `int foo(int) const;` in the class declaration. – CB Bailey Sep 10 '10 at 15:15

6 Answers6

4

The call of const (or non-const) function doesn't depend of the constness of the parameters but only of the constness of the called object (in our case obj). Overload needs different type and (non-const const) are not, so I don't think you can overload as you are doing it. (that work because you are defining a const and a non-const methods but that's not overloading.) To persuade yourself, try to remove the const at the end of your declaration to see if you are allowed to declare

int foo(int a);
int foo(const int a);

You'll get an error.

In the second case you think foo is expecting a const int as argument but not. const is tied to a not to int. So what it says is foo expect an int, you could refer it using a and that will be const : you are not allowed to modify a. That's why the const (of a parameter) doesn't appear in the function signature (that would be different for a reference).
The const outside the function refers to object called , so that's part of the signature

int foo(int a); # type => int (Test::*)(int)
int foo(const int a) const; # => int (const Test::*)(int)

int foo(const int a) ; # => int (Test::*)(int)
int foo(int a) const; # => int (const Test::*)(int)

(I'm not 100% sure about the type syntax , so don't comment on it, that's just to give an idea)

As you can see the const get removed with a. You can also write it int const a, even if not the standard way to do it, it's perfectly legal.

By the way , your code will never do what you are expected, you should use a reference to an int to modify it

int Test::foo(int &a) ...
mb14
  • 22,276
  • 7
  • 60
  • 102
  • just my point why does the compiler not give error even with const at the end then seems kinda redundant...yeah i tried that earlier in my previous trial. – Sii Sep 10 '10 at 11:07
  • because when you add const at the end, you are defining a const method, and you can define a const and a non-const method with the same name and the same parameters. But that's not overloading. To call the const method do cast it to a const object : `static_cast(obj).foo(3)`. But in the real life I would definitely recommand to use two different names for your methods are they do different stuff. – mb14 Sep 10 '10 at 11:12
  • @mb14..if you check what ragster mentioned..you kinda get values of output right (but if i dont print CONST and NON CONST)..hmm..so i havent given up hope yet :)..yeah in RL I would do it differently. – Sii Sep 10 '10 at 11:33
  • @MrProg... I'm wondering if the compiler considers the 'const' to be irrelevant because the argument is passed by value. – skimobear Sep 10 '10 at 12:10
  • @skimobear: the const is relevant, but means you can not modify the value (inside the function). – mb14 Sep 10 '10 at 12:22
  • @MrProg: Your variable is incremented indeed , because you put variable++ (not because of the a++ in no-const-foo). Not sure what you are trying to achieve anyway. – mb14 Sep 10 '10 at 12:24
4

In C++, the function signatures

int Test::foo (const int a) const

and

int Test::foo (int a) const

are considered to be complete identical.

The reason that the const on the parameter is disregarded is because it can not affect the caller in any way. As the parameter is passed by value, a copy is made of the value provided by the caller. To the caller, it does not matter in any way if the called function can change that copy or not. For this reason, C++ ignores a top-level const-qualification on function parameters (top-level const can not occur if passing a reference), and goes even as far that int foo(int); is considered a correct prototype for the function

int foo(const int)
{
    /* ... */
}

In short, it is impossible in C++ to overload a function on the constness of (value) function parameters. To get the output you want, you could consider using a non-const reference parameter for your non-const overload.

Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
2

Okay, this is how it works:

When you call a function, the value of the parameters are passed to the function. If you pass a value, then this value will be what the function gets. If you pass a pointer, then your function will get a pointer.

When your function receives the argument, all it sees is an integer value. It cannot determine where this value came from, and cannot be static or non static. These properties belong to pointers, which indicate whether or not you can change the value pointed to by the pointers, not the pointers themselves.

Just for good measure, all these function calls look IDENTICAL to the function that recieves them:

int i=1;
int* b = new int;
*b = 4;
func(5);
func(3+2);
func(i+4);
func(*b+1);

So to answer your question, what you are doing is not possible.

EDIT: To change the variable, overload the function with an int, and an int pointer. By passing the address of an int value to the function, your function can change it.

Alexander Rafferty
  • 6,134
  • 4
  • 33
  • 55
  • yeah I dont want that to happen..*keeps thinking* – Sii Sep 10 '10 at 10:55
  • This answer is using just the C subset of C++. In C++ it is preferred to use references. All those calls can be matched by a function that takes a `const int &` or a function that takes a `int` (constness in pass-by-values is discarded by the compiler when parsing the declaration). None of them will match the argument of a function taking a non-const reference. – David Rodríguez - dribeas Sep 10 '10 at 11:02
1

Yep, I can't make it call the const version - unless I do this:

const Test obj2;
output=obj2.foo(3);        // Call the const function 

No matter what parameter is passed in, if it can call the non-const, it will. If you have a const object, it calls the const version of the function.

Interesting.

Ragster
  • 717
  • 3
  • 6
0

Just a clarification. However, we are allowed to overload pointers with and without const arguments in functions, right?

As in,

int Test::foo (const int* a);
int Test::foo (int* a);

How is this different?

Nithin
  • 153
  • 3
  • 6
-1

Convert you const int to a string, overload your foo with a string and convert back...

Feel free to destroy my answer and the comments.

Cedric H.
  • 7,980
  • 10
  • 55
  • 82
  • @Cedric..if you look that wasnt my point..i wanted to use the same datatype ..in the case you mentioned I lets say a const string and string that may vary. PS. no downvote from me – Sii Sep 10 '10 at 10:53
  • Understood, was just kind of a joke because you looked "desperate" to make it works... – Cedric H. Sep 10 '10 at 10:54
  • haha..I kinda took it up as a challenge..if check the link it was from another question here in SO I am just trying to break the boundaries. – Sii Sep 10 '10 at 10:57