¿Hay alguna circunstancia en la que sea legítimo que una clase derivada tenga un destructor no virtual?
Sí.
Un destructor no virtual significa que una clase no se debe utilizar como una clase base.
No realmente; un destructor no virtual significa que eliminar una instancia de derived
mediante un puntero base
no funcionará. Por ejemplo:
class Base {};
class Derived : public Base {};
Base* b = new Derived;
delete b; // Does not call Derived's destructor!
Si usted no hace delete
de la manera anterior, entonces estará bien. Pero si ese es el caso, entonces probablemente estarías usando composición y no herencia.
Will tener un destructor no virtual de un acto de la clase derivada como una forma débil del modificador final de Java?
No, porque virtual
-ness se propaga a las clases derivadas.
class Base
{
public:
virtual ~Base() {}
virtual void Foo() {};
};
class Derived : public Base
{
public:
~Derived() {} // Will also be virtual
void Foo() {}; // Will also be virtual
};
No hay un mecanismo de lenguaje incorporado en C++ 03 o anterior para evitar subclases (*). Lo cual no es un gran problema, ya que siempre debe prefer composition over inheritance. Es decir, usa herencia cuando una relación "es-a" tiene más sentido que una verdadera relación "tiene-a".
(*) modificador 'final' se introdujo en 11
"' virtual'-ness se propaga a las clases derivadas ". ¿Lo hace? [consulta el Estándar]. Lo hace, 12.4.7: "Si una clase tiene una clase base con un destructor virtual, su destructor (ya sea declarado por el usuario o implícitamente) es virtual. – Raedwald
En una nota relacionada, si tiene una clase Base no virtual, y usted tiene algunos métodos virtuales en su clase derivada, entonces 'Base * b = new Derived(); delete b;' será un comportamiento indefinido y posiblemente bloqueará su programa. Parece bastante seguro, pero no lo es. (Es porque 'b 'no apuntará al 'inicio' del objeto' Derived' - será compensado por el espacio necesario para el vtable. Entonces, el 'delete' no funcionará exactamente en la misma dirección que el' new', y por lo tanto, no es una dirección válida para liberar. Si va a tener métodos virtuales en cualquier lugar, ponga un nombre de usuario virtual en la base. –