virtuales una sirve que puro protegidos polimorfismo para modificador metodo herencia heredadas funcion destructores clases atributos c++ inheritance virtual-destructor

sirve - ¿Por qué debería declarar un destructor virtual para una clase abstracta en C++?



para que sirve una funcion virtual en c++ (7)

Decidí investigar un poco y tratar de resumir tus respuestas. Las siguientes preguntas lo ayudarán a decidir qué tipo de destructor necesita:

  1. ¿Su clase está destinada a ser utilizada como una clase base?
    • No: declare el destructor público no virtual para evitar el v-pointer en cada objeto de la clase * .
    • Sí: Lee la siguiente pregunta.
  2. ¿Es su clase base abstracta? (es decir, cualquier método virtual puro?)
    • No: trate de hacer su clase base abstracta rediseñando su jerarquía de clases
    • Sí: Lee la siguiente pregunta.
  3. ¿Quieres permitir la eliminación polimórfica a través de un puntero base?
    • No: declare el destructor virtual protegido para evitar el uso no deseado.
    • Sí: declare el destructor virtual público (sin gastos generales en este caso).

Espero que esto ayude.

* Es importante tener en cuenta que no hay forma en C ++ de marcar una clase como final (es decir, no subclassable), por lo que, en el caso de que decida declarar su destructor no virtual y público, recuerde advertir explícitamente a sus compañeros programadores contra derivado de tu clase.

Referencias

Sé que es una buena práctica declarar destructores virtuales para clases base en C ++, pero ¿siempre es importante declarar destructores virtual incluso para clases abstractas que funcionan como interfaces? Proporcione algunos motivos y ejemplos por qué.


Es aún más importante para una interfaz. Cualquier usuario de tu clase probablemente mantendrá un puntero a la interfaz, no un puntero a la implementación concreta. Cuando lleguen a eliminarlo, si el destructor no es virtual, invocarán el destructor de la interfaz (o el valor predeterminado proporcionado por el compilador, si no especificaste uno), no el destructor de la clase derivada. Fuga de memoria instantánea.

Por ejemplo

class Interface { virtual void doSomething() = 0; }; class Derived : public Interface { Derived(); ~Derived() { // Do some important cleanup... } }; void myFunc(void) { Interface* p = new Derived(); // The behaviour of the next line is undefined. It probably // calls Interface::~Interface, not Derived::~Derived delete p; }


Kevin, en primer lugar, por favor, no te precipites en tus comentarios en nuestra discusión previa personalmente, no tenía la intención de salir tan duramente. De todos modos, la respuesta principal a la pregunta.

No siempre es obligatorio, pero considero que es una buena práctica. Lo que hace es permitir que un objeto derivado sea eliminado de manera segura mediante un puntero de tipo base.

Así por ejemplo:

Base *p = new Derived; // use p as you see fit delete p;

está mal formado si Base no tiene un destructor virtual, porque intentará eliminar el objeto como si fuera una Base * .


La respuesta a su pregunta es a menudo, pero no siempre. Si su clase abstracta prohíbe a los clientes llamar a eliminar en un puntero al mismo (o si así lo indica en su documentación), usted es libre de declarar un destructor virtual.

Puede prohibir a los clientes llamar a eliminar en un puntero haciendo que su destructor esté protegido. Trabajando así, es perfectamente seguro y razonable omitir un destructor virtual.

Eventualmente terminará sin una tabla de métodos virtuales, y terminará señalando a sus clientes su intención de hacerlo no eliminable a través de un puntero al mismo, por lo que tiene razón para no declararlo virtual en esos casos.

[Ver el punto 4 en este artículo: http://www.gotw.ca/publications/mill18.htm ]


La respuesta es simple, necesitas que sea virtual, de lo contrario la clase base no sería una clase polimórfica completa.

Base *ptr = new Derived(); delete ptr; // Here the call order of destructors: first Derived then Base.

Preferiría la eliminación anterior, pero si el destructor de la clase base no es virtual, solo se llamará al destructor de la clase base y todos los datos en la clase derivada permanecerán sin recuperar.


No es solo una buena práctica. Es la regla # 1 para cualquier jerarquía de clases.

  1. La clase más básica de una jerarquía en C ++ debe tener un destructor virtual

Ahora para el por qué Tome la jerarquía animal típica. Los destructores virtuales pasan por el despacho virtual como cualquier otra llamada a método. Toma el siguiente ejemplo.

Animal* pAnimal = GetAnimal(); delete pAnimal;

Supongamos que Animal es una clase abstracta. La única forma en que C ++ conoce el destructor adecuado para llamar es mediante el envío de métodos virtuales. Si el destructor no es virtual, simplemente llamará al destructor de Animal y no destruirá ningún objeto en las clases derivadas.

La razón para hacer que el destructor sea virtual en la clase base es que simplemente elimina la elección de las clases derivadas. Su destructor se vuelve virtual por defecto.


Sí, siempre es importante. Las clases derivadas pueden asignar memoria o mantener la referencia a otros recursos que deberán limpiarse cuando se destruya el objeto. Si no le da a sus interfaces / clases abstractas los destructores virtuales, cada vez que elimine una instancia de clase derivada mediante un manejador de clase base, no se invocará el destructor de la clase derivada.

Por lo tanto, estás abriendo el potencial de fugas de memoria

class IFoo { public: virtual void DoFoo() = 0; }; class Bar : public IFoo { char* dooby = NULL; public: virtual void DoFoo() { dooby = new char[10]; } void ~Bar() { delete [] dooby; } }; IFoo* baz = new Bar(); baz->DoFoo(); delete baz; // memory leak - dooby isn''t deleted