Considering the following piece of code.
#include <iostream>
using namespace std;
class Object
{
public:
Object() {}
void Print() const
{
cout << "const" << endl;
}
void Print()
{
cout << "mutable" << endl;
}
};
void print_obj(const Object& obj)
{
obj.Print();
}
int main()
{
Object obj1;
const Object obj2;
Object*const pobj1 = &obj1;
print_obj(obj1);
print_obj(obj2);
obj1.Print();
obj2.Print();
pobj1->Print();
return 0;
}
The output is
const
const
mutable
const
mutable
I am wondering, how does C++ decide which method to invoke, when facing many mutable methods with the same name?
print_obj(obj1);
print_obj(obj2);
The function to be called is evaluated on the basis of the cv-qualifier(const
/volatile
) of the passed object. Note that cv-qualifiers are considered while function overload resolution.
If passed object is const
, function receiving const
argument is selected.If passed object is non-const then function receiving non-const argument is selected.
obj1.Print();
obj2.Print();
pobj1->Print();
If the object is const
then only call const
member function can be called.
If the object is non-const then the non-const version is prefferred over the const
version.
The rules are clearly specified by the standard.
Reference:
C++03 standard:
§13.3.1 Candidate functions and argument lists:
For non-static member functions, the type of the implicit object parameter is “reference to cv
X
” whereX
is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [Example: for a const member function of classX
, the extra parameter is assumed to have type “reference to constX
”. ]
So if the object is const
compiler will pick version of member function which has implicit object parameter of type reference to const Object
which is const version of Print()
.
The same way all function overloading works.
When considering a member function for overloading, it includes the implicit this
parameter. If the function is declared const
, then the this
parameter is const Object *
. If the function is not const
then the this
parameter is Object *
. Since const
qualifiers affect the function overloading rules, this means that the const
ness of a function also affects the function overloading rules.
In your specific example, print_obj(obj1)
prints const
because print_obj()
is declared as taking a const Object&
, which means it will always invoke the const
version of Print()
. Same thing with print_obj(obj2)
.
obj1.Print()
prints mutable
because obj1
is not const
, therefore the non-const
version of Print()
is a better match and is picked for the function overload resolution.
obj2.Print()
prints const
because obj2
is const
, therefore the const
version of Print()
is the only function overload that's suitable.
pobj1->Print()
prints mutable
because *pboj1
is a non-const
value, so the non-const
version of Print()
is picked for the function overload resolution.
The simplest way to think about it is, what would happen if you simply had
void Print(Object &obj);
void Print(const Object &obj);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With