¿Debería cada clase tener un destructor virtual?

votos
45

Java y C # admiten la noción de clases que no se pueden usar como clases base con las palabras clave finaly sealed. En C ++, sin embargo, no hay una buena manera de evitar que una clase se derive de lo cual deja al autor de la clase con un dilema, ¿debería cada clase tener un destructor virtual o no?


Editar: Dado que C ++ 11 ya no es cierto, puede especificar que una clase es final.


Por un lado, dar a un objeto un destructor virtual significa que tendrá un vtabley, por lo tanto, consumirá 4 (u 8 máquinas de 64 bits) bytes adicionales por objeto para el vptr.

Por otro lado, si alguien más tarde deriva de esta clase y elimina una clase derivada a través de un puntero a la clase base, el programa estará mal definido (debido a la ausencia de un destructor virtual), y la optimización franca para un puntero por objeto es ridículo.

En la mano de agarre que tiene un destructor virtual (podría decirse) anuncia que este tipo está destinado a ser utilizado polimórficamente.

Algunas personas piensan que necesitas una razón explícita para no usar un destructor virtual (como es el subtexto de esta pregunta ) y otros dicen que debes usarlas solo cuando tienes razones para creer que tu clase se derivará de, ¿qué haces ? ¿pensar?

Publicado el 09/12/2008 a las 19:56
fuente por usuario
En otros idiomas...                            


8 respuestas

votos
53

Cada clase abstracta debe tener una,

  • destructor protegido, o
  • destructor virtual.

Si tiene un destructor público no virtual, eso no es bueno, ya que permite a los usuarios eliminar a través de ese puntero un objeto derivado. Como todos sabemos, ese es un comportamiento indefinido.

Para una clase que no se pretende borrar mediante un puntero, no existe razón alguna para tener un destructor virtual. No solo desperdiciaría recursos, sino que, lo que es más importante, daría a los usuarios una pista equivocada. Solo piense en el sentido repugnante que causaría dar std::iteratorun destructor virtual.

Respondida el 09/12/2008 a las 20:06
fuente por usuario

votos
26

La pregunta es, realmente, ¿quieres hacer cumplir las reglas sobre cómo deberían usarse tus clases? ¿Por qué? Si una clase no tiene un destructor virtual, cualquiera que use la clase sabe que no se pretende derivar de ella y qué limitaciones se aplican si la prueba de todos modos. ¿No es eso lo suficientemente bueno?

¿O necesita que el compilador arroje un error difícil si alguien se atreve a hacer algo que no había anticipado?

Proporcione a la clase un destructor virtual si desea que las personas se deriven de él. De lo contrario, no lo haga, y suponga que cualquier persona que use su código es lo suficientemente inteligente como para usar su código correctamente.

Respondida el 09/12/2008 a las 20:18
fuente por usuario

votos
8

¡No! Los destructores virtuales se usan solo cuando un objeto de una clase derivada se elimina a través de un puntero de clase base. Si su clase no pretende servir como base en este escenario, no convierta el destructor en virtual; estaría enviando un mensaje incorrecto.

Respondida el 09/12/2008 a las 20:04
fuente por usuario

votos
4

Consulta este artículo de Herb Sutter :

Directriz # 4: Un destructor de clase base debe ser público y virtual, o protegido y no virtual.

Respondida el 10/12/2008 a las 14:08
fuente por usuario

votos
2

Yo "no" a la pregunta general. No todas las clases necesitan una. Si puede saber que la clase nunca debe heredarse, entonces no hay necesidad de incurrir en la sobrecarga menor. Pero si hay una posibilidad, estar en el lado seguro y poner uno allí.

Respondida el 09/12/2008 a las 19:58
fuente por usuario

votos
0

clase base se convierte en clase abstracta, cuando contiene al menos una función virtual pura. Si la base no tiene un destructor virtual y Derivados (derivadas de la base) lo hace, entonces se puede destruir de manera segura un objeto derivado a través de un puntero de objeto derivado, pero no a través de un puntero de objeto base.

Respondida el 12/05/2010 a las 21:04
fuente por usuario

votos
0

Añadiré que ha habido momentos en los que me he rascado la cabeza por un tiempo en los destructores que no se llamaban cuando olvidé una virtual en la clase principal o secundaria. Sin embargo, creo que sé que debo buscar eso ahora. :)

Alguien podría argumentar que hay veces que la clase de padres hace algo en su destructor que un niño no debería hacer ... pero de todos modos es un indicador de que algo está mal con la estructura de tu herencia.

Respondida el 09/12/2008 a las 20:14
fuente por usuario

votos
-3
include<iostream> using namespace std;

class base {
    public: base() {
        cout << "In base class constructor" << endl;
    }

    virtual ~base() {
        cout << "in base class destuctor" << endl;
    }
};

class derived : public base {
    public: derived() {
        cout << "in derived class constructor" << endl;
    }

    ~derived() {
        cout << "in derived class destructor" << endl;
    }
};

int main() {
    base *b; // pointer to the base
    class b = new derived; // creating the derived class object using new
    keyword;
    delete b;
    return 0;
}
Respondida el 01/01/2016 a las 10:52
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more