Reputation: 110
I have 3 attempts to overload function "begin()"
class Test
{
public:
//case 1: compiler error
int begin();
const int begin();
//case 2:compiler warning: type qualifiers ignored on function return type
int begin();
const int begin() const;
//case 3: ok
int begin();
int begin() const;
};
For the two cases that build successfully, how does the compiler choose which overload is called for begin()
?
Upvotes: 0
Views: 588
Reputation: 1827
Case 1 is ambiguous cause return type doesn't participate in overload resolution, case 2 is equivalent to case 3 because const is discarded in return type In case 3:
const Test t1;
t1.begin() // calls int begin() const;
Test t2;
t2.begin() // calls int begin();
From cppreference.com:
A non-static member function can be declared with a const, volatile, or const volatile qualifier (this qualifier appears after the name of the function in function declaration). Differently cv-qualified functions have different types and so may overload each other. In the body of a cv-qualified function, the this pointer is cv-qualified, e.g. in a const member function, only other const member functions may be called normally. (A non-const member function may still be called if const_cast is applied or through an access path that does not involve this.)
Upvotes: 3
Reputation: 302718
Member functions have an implicit argument which is the instance of the class itself. So you can think your functions as really looking like:
// 1) compile-error as const-qualifications on return doesn't distinguish
// the functions - you cannot overload on return type
int begin(Test& );
const int begin(Test& );
// 2)
int begin(Test& );
const int begin(const Test& );
// 3)
int begin(Test& );
int begin(const Test& );
With the 2nd and 3rd cases, the const
-qualification on the function is equivalent to that implicit argument being a reference-to-const. So when you have something like:
Test{}.begin();
That calls begin()
using a reference to non-const Test
as the implicit first argument. Both overloads of begin()
are viable, both require no conversions, so the least cv-qualified reference is preferred, which is the non-const
-qualified function.
Instead, when you have:
(const Test{}).begin();
we're calling begin()
with a reference to const Test
. So the non-const
-qualified function is not a viable candidate (you cannot pass a const-ref to a function expecting a non-const-ref), so the best viable candidate is the only viable candidate: int begin() const
.
Upvotes: 4
Reputation: 560
A few rules to remember:
You can't overload methods based just on the return type. This leads to the error in your Case 1.
When returning by value, the const qualifier is redundant. In your case 2, compiler is warning you about this.
Every non-static method of the class has an implicit argument. On method invocation, this is assigned to the instance on which the method is invoked. The const keyword at end of method declaration(before the method body) applies to this implicit argument. What you are essentially saying is that the body of the function will not modify the state(data members) of the instance. If you call the method on a const instance, then you need to define the const method. Also, you can overload the method solely based upon the fact whether it is const or not.
Upvotes: 2