2016-05-08 2 views
6

Au cas où j'ai deux méthodes - un public, on protégé qui renvoient la référence à même membre, je reçois après erreur de compilation:C++ comment créer des accesseurs publics et protégés à même membre

'Server::getManager': cannot access protected member declared in class 'Server' 

Quand je commente hors fonction protégée, le code fonctionne. Pourriez-vous s'il vous plaît expliquer pourquoi cela se passe? Pourquoi le compilateur ne peut pas trouver la fonction publique au même membre?

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; 
} 
+3

Le compilateur trouve l'un public, mais le protégé est une meilleure correspondance. Cela correspond exactement. – chris

+0

Pourquoi auriez-vous besoin du protégé si le public rend la même chose? – wizzardmr42

+3

Les spécificateurs d'accès sont évalués après une résolution de surcharge. Ainsi, le compilateur trouve d'abord la meilleure correspondance, et * puis * vérifie si elle est accessible. Je vous suggère de simplement renommer le membre protégé, puisque vous avez évidemment l'intention de l'utiliser dans un contexte différent. – StoryTeller

Répondre

6

Why the compiler cannot find the public function to same member?

Ce n'est pas la question. Le compilateur trouve à la fois les fonctions et effectue une résolution de surcharge pour déterminer quel est le meilleur candidat viable. Les deux candidats sont les suivants:

Manager&  getManager()  // protected 
Manager const& getManager() const // public 

Pour les fonctions membres, il y a un premier paramètre d'objet implicite qui est l'instance de la classe elle-même. Dans ce cas, les deux fonctions sont:

getManager(Server&)   // protected 
getManager(Server const&) // public 

Nous invoquer sur un objet (s) qui ne sont pas const. Les deux candidats sont viables, mais le candidat public prend une référence à un pluscv - objet qualifié que le candidat protected - donc c'est moins préféré. Le standardese est dans [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.

En conséquence, le candidat protected est préféré - si c'est celui qui est appelé.

Malheureusement, c'est protected, donc l'appel est mal formé. Le contrôle d'accès est vérifié après la résolution de surcharge. Vous devrez donc restructurer votre programme d'une manière ou d'une autre. Vous pouvez simplement jeter s-const:

const Manager& m = const_cast<Server const&>(s).getManager(); 

Cela rendrait le candidat protected non viable.

+1

Vous pouvez aussi appeler getWritableManager protégé. Vous n'avez * pas * à surcharger les fonctions. –