2012-01-23 17 views
8
/*Child is inherited from Parent*/ 
class Parent { 
    public: 
    Parent() //Constructor 
    { 
     cout << "\n Parent constructor called\n" << endl; 
    } 
    protected: 
    ~Parent() //Dtor 
    { 
     cout << "\n Parent destructor called\n" << endl; 
    } 
}; 

class Child : public Parent 
{ 
    public: 
    Child() //Ctor 
    { 
     cout << "\nChild constructor called\n" << endl; 
    } 
    ~Child() //dtor 
    { 
     cout << "\nChild destructor called\n" << endl; 
    } 
}; 

int main() 
{ 
    Parent * p2 = new Child;   
    delete p2; 
    return 0; 
} 

Se eseguo il distruttore virtuale di Parent, ottengo un errore, quindi qual è lo scopo di rendere virtuale un distruttore protetto?Esiste un uso per rendere virtuale un distruttore protetto?

+1

Forse dovremmo iniziare con "perché dovresti proteggere i dtor?". –

+4

Perché hai mai voluto rendere virtuale il distruttore? Non dovresti * tu * conoscere lo scopo? Un distruttore protetto significa che gli oggetti non devono essere distrutti tramite puntatori di base, quindi il codice in 'main' è completamente sbagliato. – thiton

+0

Vedere http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors – user998692

risposta

17

Solo per fare un esempio: si supponga di avere una classe base che implementa il conteggio dei riferimenti. Si dispone di un addRef e di un metodo release e si desidera che l'oggetto venga distrutto, se (e solo) il contatore interno raggiunge lo zero tramite una chiamata a release.

Quindi, prima si desidera proteggere il distruttore (poiché si desidera solo distruggere l'oggetto dall'interno di relase).

Se si prevede di derivare dalla classe, si desidera anche avere il distruttore virtuale, poiché è necessario un distruttore virtuale ogni volta che si desidera distruggere un oggetto figlio tramite un puntatore a una classe base (grazie a @sharptooth per l'indicazione ...)

+2

No, è necessario un distruttore virtuale indipendentemente dal fatto che le classi derivate richiedano ulteriori distruzioni, altrimenti il ​​comportamento è solo indefinito. – sharptooth

+0

@sharptooth Giusto, non ci ho pensato. Risolto il problema, grazie per averlo indicato! – MartinStettner

+0

Ho visto un codice che utilizza questo trucco per forzare tutta la distruzione a passare attraverso la funzione wrapper amico C-style (definita per classe derivata). Immagino che l'intento fosse simile ma che sia stato perso sotto manutenzione. – Muxecoid

4

protected: Base::~Base(); dovrebbe essere virtuale almeno se si (piano su) l'eliminazione di tutti gli oggetti derivati ​​da Base all'interno Base o una classe derivata di Base.

+0

elimina questo; per qualsiasi oggetto figlio sconosciuto ottenuto grazie – tusharfloyd

+0

@ user1085822: Quindi mi stai ringraziando mentre non hai accettato la mia risposta. Cosa stai cercando di dirmi? – bitmask

+0

Questo non dovrebbe essere solo – ksb

5

Sì, se si intende eseguire delete this in class Parent funzioni membro che è molto comune quando si implementa IUnknown::Release() in oggetti COM.

+0

Bello. E del resto qualsiasi altra classe derivata se 'depete pBase;' attampted. – iammilind