2016-05-08 11 views
6

In caso ho due metodi - uno pubblico, uno protetto che restituiscono il riferimento alla stessa membro, vengo seguenti errore di compilazione:C++ come creare funzioni di accesso pubblici e protetti a stesso membro

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

Quando io commento funzione protetta, il codice funziona. Potresti per favore avvisare perché questo sta accadendo? Perché il compilatore non riesce a trovare la funzione pubblica per lo stesso membro?

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

Il compilatore trova quello pubblico, ma quello protetto è una corrispondenza migliore. Corrisponde esattamente. – chris

+0

Perché dovresti aver bisogno di quello protetto se quello pubblico restituisce la stessa cosa? – wizzardmr42

+3

Gli specificatori di accesso vengono valutati dopo la risoluzione di sovraccarico. Quindi il compilatore prima trova la migliore corrispondenza e * quindi * controlla se è accessibile. Suggerisco di rinominare semplicemente il membro protetto, poiché ovviamente si intende utilizzarlo in un contesto diverso. – StoryTeller

risposta

6

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

Non è questo il problema. Il compilatore trova entrambe le funzioni ed esegue la risoluzione di sovraccarico per determinare quale sia il candidato migliore possibile. I due candidati sono:

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

Per funzioni membro, v'è un parametro oggetto prima implicito che è l'istanza della classe stessa. In questo caso, le due funzioni diventano:

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

Stiamo invocando su un oggetto (s) che non è const. Entrambi i candidati sono validi, ma il candidato public prende un riferimento a uno altrocv - oggetto qualificato rispetto al candidato protected - quindi è meno preferito. Lo standardese è 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.

Di conseguenza, il candidato protected è preferito - in modo che è quello che si chiama.

Sfortunatamente, è protected, quindi chiamarlo è mal formato. Il controllo di accesso viene controllato dopo la risoluzione di sovraccarico. Quindi dovrai ristrutturare il tuo programma in qualche modo. Si potrebbe semplicemente lanciare s-const:

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

Ciò renderebbe il candidato protected non vitali.

+1

In alternativa, chiamare il getWritableManager protetto. Non * hai * per sovraccaricare le funzioni. –

Problemi correlati