2013-07-18 13 views
7

Il seguente codice genera un errore di compilazione:Perché il mio oggetto non può accedere ai membri protetti di un altro oggetto definito nella classe base comune?

'BaseTest::_protMember' : cannot access protected member declared in class 'BaseTest'

Perché non è possibile accedere alla variabile membro _protMember nel mio class SubTest anche se è protetta?

class BaseTest 
{ 
public: 
    BaseTest(){}; 

    BaseTest(int prot) 
    { 
     _protMember = prot; 
    }; 

protected: 
    int _protMember; 
}; 

class SubTest : public BaseTest 
{ 
    // followup question 
    SubTest(const SubTest &subTest) 
    { 
     _protMember = subTest._protMember; // this line compiles without error 
    }; 

    SubTest(const BaseTest &baseTest) 
    { 
     _protMember = baseTest._protMember; // this line produces the error 
    }; 
}; 

domanda ollowup:

Perché è, che nel costruttore di copia aggiunto posso accedere ai membri protetti di un altro esempio?

risposta

11

È possibile accedere solo ai membri protected dalla propria istanza della classe base ... non fornita come parametro. Si tratta davvero di incapsulamento OO. Senza questa restrizione, l'oggetto in costruzione potrebbe invalidare gli invarianti del parametro baseTest&.

In altre parole, il vostro SubTest può decidere su un ricorso per un membro protected che è in conflitto con l'uso fatto dello stesso elemento da un'altra classe -derived BaseTest (diciamo SubTest2 : BaseTest). Se il tuo codice SubTest è stato autorizzato a trafficare con i dati degli altri oggetti, potrebbe invalidare gli invarianti in un oggetto SubTest2 o ottenere alcuni valori che erano - nell'incapsulamento previsto - destinati solo a essere esposti a SubTest2 e (facoltativamente - vedi sotto) Derivati ​​SubTest2.

Followup question: Why is it, that in the added copy constructor I can access protected members of another instance?

SubTest(const SubTest& x); // can access x._protMember 
SubTest(const BaseTest& x); // cannot access x._protMember 

Le stesse intuizioni sopra spiegano perché questo è consentito: il costruttore di copia ottiene un SubTest& piuttosto che un qualsiasi vecchio oggetto derivato da BaseTest, e questo costruttore è chiaramente nel SubTest astrazione. Si presume che il codificatore SubTest abbia dimestichezza con il design/incapsulamento previsto SubTest e che il costruttore di copie abbia accesso a bypass e imponga condizioni/invarianti di post sull'altro oggetto SubTest&. (Stai copiando da un oggetto che potrebbe essere stato copiato dalla stessa funzione, quindi proteggerlo quando si trova sul lato "*this" ma non sul parametro by-ref non è affatto una protezione, anche ignorando tutti i motivi validi che potresti desiderare/bisogno di quell'accesso).

E 'possibile che un oggetto -derived SubTest verrà accidentalmente passato al costruttore di copia SubTest ("slicing"), ma anche per quello scenario la classe SubTest& può controllare se l'oggetto ulteriormente-derivato si sarebbe potuto fare qualcosa di inaspettato con _protMember - aggiunta di una dichiarazione privateusing BaseTest::_protMember; se si desidera "finalizzare" l'accesso a _protMember e vietare a qualsiasi classe derivata di utilizzarlo.

+0

Grazie per la risposta. Potresti dare un'occhiata alla mia domanda successiva che ho aggiunto (con una funzione che _can_ accede ai membri protetti di un'altra istanza. –

+0

@RonaldMcBean: Ho aggiunto alla mia risposta la risposta ("che può accedere ai membri protetti di un'altra istanza" - ma non un'istanza derivata da 'BaseTest'-but-not-'SubTest' - c'è il problema) –

+2

Questa è un'ottima risposta: mi sono imbattuto in questo problema alcuni anni fa e mi ci è voluto molto tempo per elaborare * * perché ** il compilatore si è comportato in questo modo: mi sono reso conto che i progettisti di C++ hanno fatto un ottimo lavoro nel comprendere le sottigliezze di dove si trovano le responsabilità nell'orientamento agli oggetti. – TooTone

0

Definendo _protMember come protected permettete oggetti di classi derivate per accedere propria_protMember. Ciò non significa che tutti gli oggetti delle classi derivate possono accedere a _protMember di altri oggetti.

5

È possibile accedere ai membri protected solo nell'istanza della classe.Cioè:

class SubTest : public BaseTest 
{ 
    SubTest(const BaseTest &baseTest) 
    { 
     _protMember = baseTest._protMember; 
    // ^^^^^^^^^^^ Is good because you are in the instance of its class 
     _protMember = baseTest._protMember; 
    //    ^^^^^^^^^^^^^^^^^^^^^ Produce error because you are not in the baseTest instance.    
    }; 

    // followup question 
    SubTest(const SubTest &subTest) 
    { 
     _protMember = subTest._protMember; 
     // Compile because access modifiers work on class level, and not on object level. 
    }; 
}; 

EDIT per il follow-up:

The access modifiers work on class level, and not on object level.

That is, two objects of the same class can access each others private members.

Questa è la mia fonte: Why can I access private variables in the copy constructor?

+0

Grazie per la risposta. followup nella mia domanda modificata? –

+0

Vedere la quinta riga del codice - non doveva essere '' subTest._protMember''? –

+0

@ Shumail92 In realtà no, quando l'ho postato la prima volta, il test era solo con baseTest :) modifico il mio post. –

Problemi correlati