Search code examples
c++constants

Why doesn't C++ cast to const when a const method is public and the non-const one is protected?


I created a class with two get methods, one const and one non-const. The const method is public, so users can query the vector. The non-const method is protected, so I can use it to modify the data I need.

When I try to use the class, however, and call the get method, the compiler complains that the non-const method is protected. Instead, I have to use const_cast to cast the object to const, so I can get instead the public method.

Is there a way to solve this? Why wouldn't the compiler do the cast itself, since there is a public method? If I remove the protected version and just leave the const one, it works fine, so it does do the cast in this situation. Casting to const is always safe. It's removing constness that is a problem.


Solution

  • The compiler considers accessibility after it decides what member function it wants to call. That is, protected and private functions are still visible, even though they aren't accessible.

    Why? One reason is that if you made inaccessible functions ignored by overload resolution, you could change what function is called simply by changing its accessibility. With the current rules, you can only cause compiling code to fail to compile, or cause code that currently doesn't work to compile, or change something with no effect on the meaning of the code. You cannot change access specifiers and silently cause a different function to be called.

    As a contrived example, here's a pretty terrible class interface:

    public:
        // Returns the amount of change tendered for this transaction.
        MoneyAmount change() const;
    
    private:
        // Account for a change of currency. Charges standard moneychanger's fee.
        MoneyAmount change(Currency toCurrency = Currency::USD);
    

    If inaccessible functions were removed from overload resolution, client code could call change() just fine. And if later the second change(Currency) function was made public and the first one deleted, that code would suddenly silently call another function with an entirely different purpose. The current rules prevent a change of access specifier from changing the behavior of a compiling program.