online ejemplos descargar code caracteristicas c++

ejemplos - c++ online



C++ "Funciones virtuales pero no destructores virtuales" (5)

Tengo una clase base de Media y varias clases derivadas, a saber, DVD , Book , etc. La clase base se escribe como:

class Media{ private: int id; string title; int year; public: Media(){ id = year = 0; title = ""; } Media(int _id, string _title, int _year): id(_id), title(_title), year(_year) {} // virtual ~Media() = 0; void changeID(int newID){ id = newID; } virtual void print(ostream &out); };

El problema es que, sin el destructor, GCC me da un montón de advertencias. La class has virtual functions but non-virtual destructor , pero aún así se compila y mi programa funciona bien. Ahora quiero deshacerme de esas molestas advertencias para satisfacer el compilador agregando un destructor virtual, el resultado es: no se compila, con el error:

undefined reference to `Media::~Media()`

Hacer el destructor puro virtual no resuelve el problema. entonces ¿qué ha ido mal?


La cosa es: sin el destructor, GCC me da un montón de advertencias "la clase tiene funciones virtuales pero no destructor virtual", pero aún así compila y mi programa funciona bien

Esta es una advertencia molesta en C ++ moderno, pero en C ++ de tipo objeto antiguo generalmente es correcta.

El problema es sobre la forma en que se destruyen tus objetos. Una prueba simple:

#include <iostream> class Base {}; class Derived: public Base { public: ~Derived() { std::cout << "Aargh/n"; } }; int main() { Base* b = new Derived(); Derived* d = new Derived(); delete d; delete b; }

Esto imprime:

Aargh

Sí, sólo una vez.

El problema es que cuando se llama a delete en una variable de tipo Base* , se llama al método Base::~Base() . Si es virtual , la llamada se envía dinámicamente al método final (según el tipo dinámico), en este caso Derived::~Derived() , pero si no lo es, Derived::~Derived() nunca es Llamado, así nunca ejecutado.

Por lo tanto, si desea llamar a delete (o usar punteros inteligentes que lo hacen por usted) en los tipos base, entonces necesita agregar virtual ~Base() {} en sus definiciones de clase. Es por esto que gcc le advierte cuando crea una clase polimórfica sin un destructor virtual .

Nota: el tiempo cambió y, desde entonces, implementé -Wdelete-non-virtual-dtor en Clang y también se replicó en gcc.

-Wnon-virtual-dtor es útil para escritores de bibliotecas (como advierte en la clase base), pero puede tener una tasa más alta de falsos positivos; por otra parte, -Wdelete-non-virtual-dtor dispara en el sitio de la llamada, y tiene una tasa de falsos positivos mucho más baja (con la que generalmente se puede trabajar al final para eliminar la propiedad "polimórfica" de la clase).


Debe implementar el destructor virtual, no hacerlo puramente virtual.

Mire this pregunta similar (idéntica quizás desde el punto de vista del error del destructor virtual, no la advertencia) para obtener más información.

EDITAR: solución más genérica, en respuesta al comentario de LuchianGrigore (gracias por señalarlo)

También puede hacer que el destructor sea totalmente virtual e implementarlo como se indica en la pregunta mencionada anteriormente.

El uso de destructores virtuales en sus clases debe ser para evitar la creación de instancias de la clase base (es decir, cuando no tiene otros métodos virtuales puros para hacer la clase abstracta).


Descomente la declaración primero y luego intente agregar la siguiente línea después de la declaración de clase

Media::~Media(){}


Lo que has comentado es una declaración virtual pura para un destructor. Eso significa que la función debe ser anulada en una clase derivada para poder instanciar un objeto de esa clase.

Lo que quieres es solo una definición del destructor como una función virtual:

virtual ~Media() {}


También debe definir el destructor virtual, no solo agregarlo.

//Media.h class Media{ //.... virtual ~Media() = 0; }; //Media.cpp #include "Media.h" //.... Media::~Media() {};

La razón por la que recibe las advertencias es que todas las clases que se derivarán deben tener un destructor virtual o protegido (crédito @Steve), de lo contrario, eliminar una instancia a través de un puntero a una clase base da como resultado un comportamiento indefinido.

Tenga en cuenta que TIENE QUE proporcionar una definición para los destructores, incluso si son puramente virtuales.