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()
?
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
.