Perché una class derivata non può chiamare la funzione membro protetta in questo codice?

#include  class Base { protected: void somethingProtected() { std::cout << "lala" << std::endl; } }; class Derived : public Base { public: void somethingDerived() { Base b; b.somethingProtected(); // This does not compile somethingProtected(); // But this is fine } }; int main() { Derived d; d.somethingDerived(); return 0; } 

Ho pensato che forse solo i membri protetti di this possono essere utilizzati e membri protetti di altri casi sono per sempre irraggiungibili.

Ma:

 class Derived : public Base { public: void somethingDerived(Derived& d) { d.somethingProtected(); // This compiles even though d is // potentially a different instance } void somethingDerived(Base& b) { b.somethingProtected(); // This does not } }; 

Mi sento un po ‘nauseato da questo, dal momento che ho programmato in C ++ per qualche tempo, ma non ho trovato alcuna spiegazione per questo comportamento.

MODIFICARE:

Non importa se è la stessa o un’istanza diversa:

 int main() { Derived d1, d2; // Two different instances d1.somethingDerived(d2); // This compiles fine d1.somethingDerived(d1); // This compiles fine return 0; } 

EDIT2:

Sembra che quando si tratta di diritti di accesso, non importa affatto quale istanza di una class viene utilizzata:

 class Base { public: void something(Base& b) // Another instance { ++ba; // But can enter private members } private: int a; }; 

Anche se il controllo degli accessi in C ++ funziona in base alla class (anziché in base all’istanza), l’ protected accesso protected presenta alcune peculiarità.

Le specifiche del linguaggio vogliono assicurarsi di accedere a un membro protetto di qualche base subobject appartenente alla class derivata. Non si dovrebbe essere in grado di accedere ai membri protetti di alcuni oggetti indipendenti indipendenti di tipo base. In particolare, non è ansible accedere ai membri protetti degli oggetti indipendenti di tipo base. È consentito accedere solo ai membri protetti degli oggetti di base incorporati negli oggetti derivati ​​come sottooggetti di base.

Per questo motivo, è necessario accedere ai membri protetti tramite la syntax pointer->member , reference.member o object.member , dove il puntatore / riferimento / object fa riferimento alla class derivata .

Ciò significa che nel tuo esempio, membro protetto somethingProtected() non è accessibile tramite oggetti Base , puntatori Base * o Base & riferimenti, ma è accessibile tramite oggetti Derived * , puntatori Derived * e Derived & riferimenti. Il tuo semplice accesso a somethingProtected() è permesso, poiché è solo una scorciatoia per this->somethingProtected() dove this è di tipo Derived * .

b.somethingProtected() viola i requisiti di cui sopra.

Si noti che in conformità con le regole di cui sopra

 void Derived::somethingDerived() { Base *b = this; b->somethingProtected(); // ERROR this->somethingProtected(); // OK } 

anche la prima chiamata fallirà mentre la seconda verrà compilata, anche se entrambi stanno cercando di accedere alla stessa entity framework.

Credo che tu abbia qualche confusione su come accedere ai membri della class base. È solo in questo modo:

 class Derived : public Base void drivedMethod() { Base::baseMethod(); } 

nel tuo esempio stai provando ad accedere ad un membro protetto di un’altra istanza.

Un’istanza derivata avrà accesso ai propri membri protetti ma non ad altri membri protetti da istanze di class, questo è in base alla progettazione.

Infatti, l’accesso ai membri protetti di un’altra class, da parte di altri membri dell’istanza o dalla funzione principale è in realtà entrambi sotto l’accesso pubblico …

http://www.cplusplus.com/doc/tutorial/inheritance/ (cerca la tabella degli specificatori di accesso per vedere i diversi livelli)

Entrambi gli esempi dimostrano la stessa cosa per esempio:

 void somethingDerived(Base& b) { b.somethingProtected(); // This does not 

qui la tua class derivata sta ottenendo b come parametro, quindi sta ottenendo un’altra istanza di base, quindi perché b.somethingProtected non è pubblico non lo sarà.

questo compierà:

 void somethingDerived() { Base::somethingDerived(); 

il tuo secondo esempio è soddisfacente perché stai accedendo a un metodo pubblico su un’altra class d

 > void somethingDerived(Base& b) > { > b.somethingProtected(); // This does not > } 

La class Derived può accedere solo al membro di base protetto in oggetti Derived . Non può accedere al membro in oggetti che non sono oggetti (necessariamente) Derived . Nei casi che non riescono, si sta tentando di accedere al membro tramite una Base & , e poiché ciò potrebbe fare riferimento a un object che non è Derived , l’accesso non può essere effettuato.

Quello che hai fatto è illegale in C ++. Non è ansible accedere a un membro protetto da un object di una class. Solo le funzioni membro possono accedere ai membri protetti. protected membri protected si comportano proprio come i membri privati ​​eccetto se ereditati da una class derivata. Considera il programma indicato di seguito per comprendere la differenza tra membri privati, pubblici e protetti.

 class Base { private: void somethingPrivate() { std::cout << "sasa" << std::endl; } public: void somethingPublic() { std::cout << "haha" << std::endl; } protected: void somethingProtected() { std::cout << "lala" << std::endl; } }; class Derived : public Base { public: void somethingDerived() { Base b; b.somethingPublic(); // Works fine. somethingProtected(); // This is also fine because accessed by member function. //b.somethingProtected(); // Error. Called using object b. //somethingPrivate(); // Error. The function is not inherited by Derived. } };