2010-10-15 14 views
10

Supponiamo che io ho questo codiceC++ è ancora distruttore virtuale se non ci sono membri dati in derivato?

class Base{ 
    public: 
     int getVal(); 
    private: 
     int a, b; 
}; 

class Derived::public Base{ 
    public: 
     void printVal(); 
}; 

int main(){ 
    Base *b = new Derived(); 
    delete b;  
} 

Conosco un distruttore virtuale sarebbe eliminare le cose per bene, ma è brutto da eliminare con puntatore base (quando non c'è distruttore virtuale), anche se non ci sono funzioni virtuali e non membri dei dati nella classe derivata? Cosa succederà se questo è fatto?

risposta

5

Per dati di tipo primitivo, il tuo esempio funzionerà molto probabilmente nella pratica. È un dato di fatto, incorrere in una vtable potrebbe effettivamente hinder prestazioni (quindi ci può essere qualche legittimo uso qui), ma è tecnicamente definito, a 5,3-5,4:

Se il tipo statico l'operando [del l'operatore delete] è diverso da suo tipo dinamico, il tipo statico è una classe di base di tipo dinamico dell'operando e il tipo statico è avere un distruttore virtuale o il comportamento è indefinito.

In realtà tutto dipende dalla "densità" dei dati nella classe, e poiché non ci sono membri allocati nell'heap (nel tuo caso), si dovrebbe andare bene, ma è sicuramente un odore di codice.

+2

Grazie, David. – snk

+3

È pericoloso affidarsi a cose che "probabilmente funzionano" e presuppongono che "dovrebbe andare bene". È molto meglio scrivere codice che funzionerà, quindi tu sai che starai bene. –

+0

James, mi assicurerò che ci sia sempre un distruttore virtuale. Questo è solo un ipotetico chiesto da qualcuno e non ha avuto una risposta per questo. Grazie a tutti e due. – snk

9

È errato eliminare con il puntatore di base (quando non esiste un distruttore virtuale) anche se non ci sono funzioni virtuali e nessun membro di dati nella classe derivata?

Sì.

Il comportamento non è definito indipendentemente dal contenuto della classe derivata.

Cosa succederà se questo è fatto?

Tutto può succedere.

+1

Grazie mille James. – snk

+3

+1 per "Qualcosa potrebbe accadere". Nulla! Assolutamente nulla! :) – ybungalobill

2

Il descrittore virtuale nella classe derivata è necessario per chiamare correttamente il distruttore derivato (polimorfismo), quando l'oggetto derivato viene creato tramite un puntatore alla classe di base.

Regola CPP alta integrità 3.3.2 Scrivere un distruttore "virtuale" per le classi di base. (QACPP 2116)

Motivazione: Se un oggetto verrà mai distrutto tramite un puntatore alla sua classe base, la classe base dovrebbe avere un distruttore virtuale. Se il distruttore della classe base non è virtuale, verrà invocato solo il distruttore per la classe base. Nella maggior parte dei casi, i distruttori dovrebbero essere virtuali, poiché la manutenzione o il riutilizzo possono aggiungere classi derivate che richiedono un distruttore virtuale.

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() { 
    Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
    Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
} 
+0

Penso che intendessi che il tuo distruttore sia chiamato "~ Derived", non "~ C" ... –

+0

@Mike Ellery, sì, è quello che volevo dire. Ho corretto il codice. – ArBR

Problemi correlati