Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ const and mutable functions with the same name

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?

like image 985
CuriousMind Avatar asked Sep 13 '12 04:09

CuriousMind


Video Answer


2 Answers

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” where X 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 class X, the extra parameter is assumed to have type “reference to const X”. ]

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

like image 146
Alok Save Avatar answered Sep 30 '22 21:09

Alok Save


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 constness 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);
like image 41
Lily Ballard Avatar answered Sep 30 '22 19:09

Lily Ballard