2009-05-05 8 views
14

Tengo un gran conjunto de clases heredadas (criterios) que heredan de una clase base (criterio). Aquí está el código criterion 'sVirtual Default Destructors en 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; 
}; 

Algunos ejemplos de las clases derivadas de éste:

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"); 
    }; 
}; 

Dado que no tengo un destructor aquí en absoluto, pero esto aún no se supone que es una clase base , ¿necesito insertar un destructor virtual vacío, es decir como este ?:

virtual void ~criterion() = 0; 

Si se necesita esa declaración de destructor virtual, ¿todas las clases intermedias también necesitan una? Es decir. ¿FastFilter arriba también necesitaría un destructor virtual?

+0

Lo anterior no es un destructor vacío. Es un destructor que también es una función virtual pura. Esto no tiene nada que ver con estar vacío, y de hecho el destructor es especial, ya que siempre debe tener una definición incluso cuando es puramente virtual. –

Respuesta

37

Sí, la clase base necesita un destructor virtual, incluso si está vacío. Si eso no se hace, entonces cuando algo delete es un objeto derivado a través de un puntero/referencia base, los objetos miembros del objeto derivado no tendrán la oportunidad de destruirse a sí mismos correctamente.

Las clases derivadas no necesitan declarar ni definir su propio destructor a menos que necesiten algo más que el comportamiento predeterminado del destructor.

23

La recomendación es insertar

virtual ~criterion() {} 

para evitar la supresión de un problema puntero clase base. De lo contrario, perderá memoria ya que no se invocarán los destructores de las clases derivadas.

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

¿Hay alguna razón para usar un destructor vacío sobre uno virtual puro? –

+0

Nevermind ... respondida por otra persona :) –

+1

¿No es 'virtual ~ criterion() noexcept {}' más bonita? – user1095108

12

No es necesario para hacer el resumen destructor, sólo le dan una implementación vacía:

virtual ~criterion() { } 

De esta manera no se ven obligados a ponerlo en práctica en todas las clases de niños, pero aún así cada uno de ellos tendrán un destructor virtual (heredado).

7

Un cambio pequeño de lo que otros ya han contestado:

En lugar de

virtual void ~criterion() = 0; 

la versión requerida es:

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

Para saber más sobre destructor virtual echar un vistazo a este enlace de la pregunta frecuente When should my destructor be virtual?