2009-05-05 14 views
14

Ho una vasta serie di classi ereditate (criteri) che ereditano da una classe base (criterio). Ecco il codice criterion 'sVirtual Default Destructors in C++

class criterion 
{ 
public: 
    virtual unsigned __int32 getPriorityClass() const = 0; 
    virtual BOOL include(fileData &file) const = 0; 
    virtual void reorderTree() = 0; 
    virtual unsigned int directoryCheck(const std::wstring& directory) const = 0; 
    virtual std::wstring debugTree() const = 0; 
}; 

Alcuni esempi di classi derivate da questo:

class fastFilter : public criterion 
{ 
public: 
    void reorderTree() {}; 
    unsigned int directoryCheck(const std::wstring& /*directory*/) const { return DIRECTORY_DONTCARE; }; 
    unsigned __int32 getPriorityClass() const { return PRIORITY_FAST_FILTER; }; 
}; 

class isArchive : public fastFilter 
{ 
public: 
    BOOL include(fileData &file) const 
    { 
     return file.getArchive(); 
    } 
    std::wstring debugTree() const 
    { 
     return std::wstring(L"+ ISARCHIVE\n"); 
    }; 
}; 

Dato che non ho un distruttore qui a tutti, ma tuttavia questa dovrebbe essere una classe base , ho bisogno di inserire un distruttore virtuale vuoto, IE come questo ?:

virtual void ~criterion() = 0; 

Se è necessaria la dichiarazione del distruttore virtuale, anche tutte le classi intermedie ne hanno bisogno? Cioè fastFilter di cui sopra ha bisogno anche di un distruttore virtuale?

+0

Quanto sopra non è un distruttore vuoto. È un distruttore che è anche una pura funzione virtuale. Questo non ha nulla a che fare con l'essere vuoti, e infatti il ​​distruttore è speciale in quanto deve sempre avere una definizione anche quando è puro virtuale. –

risposta

37

Sì, la classe base richiede un distruttore virtuale, anche se vuoto. Se ciò non avviene, quando qualcosa di delete è un oggetto derivato attraverso un puntatore/riferimento di base, gli oggetti membro dell'oggetto derivato non avranno la possibilità di distruggere se stessi correttamente.

Le classi derivate non hanno bisogno di dichiarare o definire il proprio distruttore a meno che non abbiano bisogno di qualcosa di diverso dal comportamento predefinito del distruttore.

23

La raccomandazione è quella di inserire

virtual ~criterion() {} 

per evitare la cancellazione fuori un problema di base puntatore di classe. Altrimenti si verificherà una perdita di memoria in quanto i distruttori delle classi derivate non verranno richiamati.

criterion *c = new fastFilter(); 
delete c; // leaks 
+1

C'è qualche ragione per usare un distruttore vuoto su uno virtuale puro? –

+0

Nevermind ... risposto da qualcun altro :) –

+1

Non è 'virtuale ~ criterio() noexcept {}' più carino? – user1095108

12

Non è necessario per rendere l'astratto distruttore, basta dargli un'implementazione vuoto:

virtual ~criterion() { } 

In questo modo non si è costretti ad attuarlo in ogni classe bambino, ma comunque ognuno di loro avranno un distruttore virtuale (ereditato).

7

Un piccolo cambiamento da ciò che altri hanno già risposto:

Invece di

virtual void ~criterion() = 0; 

la versione richiesta è:

virtual ~criterion() {} //Note: Removed void as destructors not allowed 
          // a return type 

Per sapere di più su distruttore virtuale dare un'occhiata a questo collegamento da domande frequenti When should my destructor be virtual?