2010-07-14 10 views
41

Ho avuto un errore ieri e, mentre è facile spostarsi, volevo essere sicuro di capire bene il C++.Accesso a membri protetti in una classe derivata

Ho una classe base con un membro protetto:

class Base 
{ 
    protected: 
    int b; 
    public: 
    void DoSomething(const Base& that) 
    { 
     b+=that.b; 
    } 
}; 

Questo compila e funziona bene. Ora mi rivolgo Base, ma ancora voglia di usare B:

class Derived : public Base 
{ 
    protected: 
    int d; 
    public: 
    void DoSomething(const Base& that) 
    { 
     b+=that.b; 
     d=0; 
    } 
}; 

nota che in questo caso DoSomething è ancora in corso un riferimento a un Base, non Derived. Mi aspetto che possa ancora accedere a that.b all'interno di Derived, ma ottengo un errore cannot access protected member (MSVC 8.0 - non ho ancora provato gcc).

Ovviamente, l'aggiunta di un getter pubblico su b ha risolto il problema, ma mi chiedevo perché non potessi accedere direttamente a b. Tuttavia, se si utilizza l'ereditarietà pubblica, le variabili protette sono ancora visibili alla classe derivata.

+2

Controlla http://www.gotw.ca/gotw/076.htm (Nota: non usare quella roba nel codice di produzione). – Brian

risposta

29

È possibile accedere ai membri protetti solo in casi del tipo (o derivati ​​dal proprio tipo).
Non è possibile accedere ai membri protetti di un'istanza di un genitore o di un cugino.

Nel tuo caso, la classe Derived può accedere solo il membro b di un'istanza Derived, non di un diverso Base istanza.

Anche la modifica del costruttore per prendere un'istanza Derived risolverà il problema.

+0

Intendi dire che possiamo accedere ai membri protetti dai nostri oggetti non dagli oggetti della classe base? Se sì, allora perché è così? –

+1

@AnishaKaul: puoi accedere solo ai membri protetti della classe base in un'istanza del tuo tipo, non di tipo cugino. Ad esempio, 'Button' non può accedere a una proprietà protetta da' Control' su un 'TextBox'. – SLaks

+1

'È possibile accedere ai membri protetti della classe base 'solo in un'istanza del proprio tipo, non in un tipo di cugino'. È stata nuovamente scritta la stessa frase che ha scritto sopra. Si prega di dare un'occhiata qui: http: //stackoverflow.com/questions/9139824/how-to-access-protected-members-in-a-ivedived-class –

3

È possibile accedere ai membri protetti di Derived, ma non quelli di Base (anche se l'unico motivo per cui è un membro protetto di Derived è perché è ereditata da Base)

+1

Questo non funziona. Considera "Hai accesso ai membri" privati ​​"di" Derivato "." e le implicazioni per i membri 'privati' ereditati di 'Base'. –

2

Come detto, è solo il modo in cui il linguaggio funziona.

Un'altra soluzione è quella di sfruttare l'eredità e passare al metodo genitore:

class Derived : public Base 
{ 
    protected: 
    int d; 
    public: 
    void DoSomething(const Base& that) 
    { 
     Base::DoSomething(that); 
     d=0; 
    } 
}; 
+1

Ho dato un cattivo esempio nella domanda, ma non posso chiamare Base :: DoSomething perché in realtà DoSomething sta facendo diversamente quando si tratta di una derivata piuttosto che di una base. – miked

-3

Usa this puntatore per accedere ai membri protetti

class Derived : public Base 
{ 
    protected: 
    int d; 
    public: 
    void DoSomething(const Base& that) 
    { 
     this->b+=that.b; 
     d=0; 
    } 
}; 
+1

Questa risposta è sbagliata. La classe derivata non può accedere a "b" della classe base in quanto è dichiarata come protetta (questo è ciò che l'utente ha chiesto in primo luogo). Questo codice genererà un errore del compilatore. – tantuni

+1

Che non risposta. È il 'b' di' that' che è il problema. E aggiungere "this->" non è solo non correlato ma anche un no-op completo perché è implicito se omesso. Vorrei che le persone conoscessero un minimo di una lingua e testare qualsiasi codice che scrivono prima di postarlo come risposta. –

0

protected i membri possono essere raggiunti:

  • tramite il puntatore this
  • o allo stesso tipo protetto i membri, anche se dichiarati nella base di
  • o dalle classi amico, funzioni

per risolvere il tuo caso è possibile utilizzare una delle ultime due opzioni.

subisci percepite in Derived :: DoSomething o dichiarare Derivato friend di Base:

class Derived; 

class Base 
{ 
    friend class Derived; 
    protected: 
    int b; 
    public: 
    void DoSomething(const Base& that) 
    { 
     b+=that.b; 
    } 
}; 

class Derived : public Base 
{ 
    protected: 
    int d; 
    public: 
    void DoSomething(const Base& that) 
    { 
     b+=that.b; 
     d=0; 
    } 
}; 

Si può anche considerare getter pubblici in alcuni casi.

Problemi correlati