2009-10-16 12 views
7

I dont completamente capito questo:ereditarietà privata

class Base 
{ 
    public: 
    Base() 
    { 
     cout<<"Base" << endl; 
    } 

    virtual void call() 
    { 
     cout<<"Base call" << endl; 
    } 
}; 

class Derived: private Base 
{ 
    public:  
    Derived() 
    { 
     cout<<"Derived" << endl; 
    } 
}; 

int main(void) 
{ 
    Base *bPtr = new Derived(); // This is not allowed 
} 

Forse perché qualcuno potrebbe chiamare call() utilizzando bPtr che in realtà è fatto in oggetto derivato? O c'è qualche altra ragione?

risposta

18

Da una comprensione comune di eredità, ‘l'ereditarietà privata’ C++’è un termine improprio orribile: è non eredità (per quanto tutto al di fuori della classe è interessato), ma un dettaglio completo implementazione della classe.

Visto dall'esterno, l'ereditarietà privata è praticamente uguale alla composizione. Solo all'interno della classe ottieni una sintassi speciale che ricorda più l'ereditarietà della composizione.

Esiste tuttavia un avvertimento: C++ lo tratta sinteticamente come ereditarietà, con tutti i vantaggi e i problemi che ciò comporta, come ad esempio scope visibility and accessibility. Inoltre, calchi in stile C (! Ma nessuno C++ espressi) in realtà ignora la visibilità e quindi riesce a lanciare il puntatore Derived-Base:

Base* bPtr = (Base*) new Derived(); 

Inutile dire, questo è il male .

+7

È l'ereditarietà dell'implementazione piuttosto che l'ereditarietà dell'interfaccia. –

+0

@Laurence: vero, ma questa è solo una discussione sulla terminologia. Ero preoccupato per la vista esterna sulla classe. –

+1

"_it is not inheritance_" Assolutamente sbagliato. È ** eredità **, con accesso privato. – curiousguy

0

Con l'ereditarietà privata, si perde l'opzione per trattare l'oggetto derivato come oggetto della classe base.

1

Se si eredita privatamente qualsiasi codice che richiede la conversione da Derivato * a Base * deve essere un membro o un amico della classe derivata.

+0

Grazie per le risposte, ma in realtà volevo sapere perché non consentivano che ciò accadesse. –

+0

@nitinsoman Perché ** tu ** hai scritto 'private'. Questo è ciò che l'accesso privato significa ... qual è la tua domanda? – curiousguy

9

Perché private significa "dettagli di implementazione", il che rende il fatto che Derived deriva da Base un dettaglio di implementazione.

L'ereditarietà privata non è l'ereditarietà dell'interfaccia, ma l'ereditarietà dell'implementazione. Non implementa una relazione "Is-A", ma una relazione "Is-Implemented-Using". Derived non è un Base per quanto riguarda gli utenti delle classi, capita solo di (attualmente) essere implementato usandolo.

+0

Impressionante spiegazione in frasi così piccole +1 –

17

L'ereditarietà pubblica significa che tutti sanno che Derivato è derivato dalla base.

eredità protetta significa che solo derivata, gli amici di Derivato, e le classi derivate da un know derivata che Derivato è derivato da Base. *

eredità privata significa che solo derivati ​​e gli amici di know derivata che deriva deriva dalla Base .

Poiché è stata utilizzata l'ereditarietà privata, la funzione main() non ha alcun indizio sulla derivazione dalla base, quindi non può assegnare il puntatore.

L'ereditarietà privata viene in genere utilizzata per soddisfare la relazione "è implementata nei termini di". Un esempio potrebbe essere che Base espone una funzione virtuale che è necessario sovrascrivere - e quindi deve essere ereditata da - ma non vuoi che i client sappiano che hai questa relazione di ereditarietà.

* anche: quanto legno sarebbe una marmotta chuck ...

+4

Tre anni e mezzo dopo, e un addendum alla mia risposta: nel caso dell'eredità privata, nota che nemmeno Base sa che Derivato è derivato da Base. Ossia, 'dynamic_cast (this)' in una funzione membro di Base restituirà sempre NULL se Derivato eredita privatamente da Base. Lo dico perché mi ha morso di recente quando tentavo l'ereditarietà privata di una classe passata attraverso il modello di modello ricorsivo curiosamente. –