In case I have two methods - one public, one protected that return the reference to same member, I get following compilation error:
'Server::getManager': cannot access protected member declared in class 'Server'
When I comment out protected function, code works. Could you please advise why this is happening? Why the compiler cannot find the public function to same member?
class Manager
{
};
class Server
{
public:
const Manager & getManager() const { return m_man; }
protected:
Manager & getManager() { return m_man; } // <-- after removing this method I get no compilation error
private:
Manager m_man;
};
int main()
{
Server s;
const Manager& m = s.getManager();
return 0;
}
Public, private and protected are called access modifiers.
Protected members that are also declared as static are accessible to any friend or member function of a derived class. Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
Protected members in a class are similar to private members as they cannot be accessed from outside the class. But they can be accessed by derived classes or child classes while private members cannot.
Friend function can access all private, protected and public data members of a class. So option D is right. Friend function can access protected and public members of both classes and it can also access private members by using object of that class.
Why the compiler cannot find the public function to same member?
That's not the issue. The compiler finds both functions and performs overload resolution to determine which is the best viable candidate. The two candidates are:
Manager& getManager() // protected
Manager const& getManager() const // public
For member functions, there is an implicit first object parameter that is the instance of the class itself. In this case, the two functions become:
getManager(Server& ) // protected
getManager(Server const& ) // public
We're invoking it on an object (s
) that is not const
. Both candidates are viable, but the public
candidate takes a reference to a more cv-qualified object than the protected
candidate - so it's less preferred. The standardese is in [over.ics.rank]:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
— S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.
As a result, the protected
candidate is preferred - so that's the one that's called.
Unfortunately, it's protected
, so calling it is ill-formed. The access control is checked after overload resolution. So you'll have to restructure your program somehow. You could simply cast s
to const
:
const Manager& m = const_cast<Server const&>(s).getManager();
This would make the protected
candidate non-viable.
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