¿Forzar destructores virtuales? C++
virtual-destructor (4)
No vi la respuesta a esto en el C ++ Faq lite:
¿Cómo defino una clase base para que cada clase que la hereda sea necesaria para definir un destructor?
Intenté ejecutar este programa
struct VDtor { virtual ~VDtor()=0; };
struct Test:VDtor { virtual ~Test(){} };
int main() { delete new Test; return 0; }
http://codepad.org/wFcE71w3 Con el error
In function `Test::~Test()'':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()''
In function `Test::~Test()'':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()''
Entonces, ¿es posible?
Cada clase tiene un destructor, independientemente. La declaración de un destructor virtual en la base garantiza que los niños tengan destructores virtuales. Esto no significa que el codificador deba declarar explícitamente un destructor, de todos modos no sería algo bueno. Todo lo que significa es que, si se declara un destructor, será virtual.
Cuando se destruye la Prueba, llamará a su destructor de clase base, que no existe. Solo debes declararlo vacío si no tienes la lógica de destrucción necesaria.
Es "posible" en algún sentido (si su objetivo era que la clase derivada se mantenga abstracta de lo contrario). Pero no le dará el resultado que le gustaría: porque el compilador creará un destructor implícitamente si el programador no lo ha hecho.
Por lo tanto, no es posible forzar al autor de la clase derivada a declarar explícitamente un constructor.
(Editar: como se anotó en @chubsdad notas , el error en su código en particular es porque necesita definir el destructor declarado explícitamente de la clase base).
Edición : solo por diversión, hay situaciones que requieren un constructor declarado explícitamente. Considera lo siguiente
struct Viral {
struct Dose { };
protected:
~Viral() throw (Dose) { }
};
struct Base {
virtual ~Base() throw() { }
};
struct Derived : Base, Viral { };
Este código no se compilará porque el ~Derived
declarado implícitamente tendrá una throw (Dose)
especificación de excepción throw (Dose)
que es más flexible que la que tiene ~Base
, por lo que viola el requisito de que los anuladores no deben tener una especificación de excepción más suelta. Deberá declarar explícitamente el destructor adecuadamente.
struct Derived : Base, Viral { ~Derived() throw() { } };
Pero esta no es realmente una solución a su problema, porque las clases derivadas deben "cooperar" para derivar de Viral
o ponerlo como un miembro de datos no estáticos. También es muy feo :)
Edit: Lo siguiente parece ser una forma estándar de hacerlo
struct Viral {
struct Dose { };
protected:
~Viral() throw (Dose) { }
};
struct Base : virtual Viral {
virtual ~Base() throw() { }
};
Clang y GCC ( comenzando con v4.6 ) rechazan cualquier clase derivada de Base
que tenga un destructor declarado implícitamente, debido a que tiene una especificación de excepción incompatible (cualquier clase derivada llamará ~Viral
directamente, en lugar de indirectamente llamando a ~Base
, el Estándar dice). Comeau acepta esto, pero sospecho que no es conforme a este respecto.
struct VDtor { virtual ~VDtor()=0; };
VDtor::~VDtor () { } // <== Implementation.
struct Test:VDtor { ~Test(){} };
int main() { delete new Test; return 0; }
Para corregir el error, debe implementar el VDtor :: ~ VDtor () como se muestra arriba.