Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ how to create public and protected accessors to same member

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;
}
like image 704
Zheden Avatar asked May 08 '16 19:05

Zheden


People also ask

What is public/private & protected as together called?

Public, private and protected are called access modifiers.

Can protected members be accessed by member functions?

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.

Are protected members accessible outside the 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.

Can access private and protected members of a class?

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.


1 Answers

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.

like image 142
Barry Avatar answered Oct 12 '22 10:10

Barry