poo implementar ejemplo destructores delete constructores como c++ virtual-destructor

implementar - destructor c++ ejemplo



¿Cuándo debería ser tu destructor virtual? (6)

Posible duplicado:
¿Cuándo usar destructores virtuales?

¿Cuándo debería ser virtual el destructor de su objeto C ++?


Recientemente llegué a la conclusión de que la respuesta correcta es la siguiente:

Pauta nº 4: Un destructor de clase base debe ser público y virtual, o protegido y no virtual.

Y, por supuesto, Herb Sutter da la razón de su afirmación. Tenga en cuenta que va más allá de las respuestas habituales "cuando alguien elimine un objeto de clase derivada a través de un puntero de clase base" y "haga que su destructor sea virtual si su clase tiene alguna función virtual".


  1. Necesita un destructor virtual cuando al menos uno de los métodos de clase es virtual.

Esto se debe a que el motivo del método virtual es que desea utilizar el polimorfismo. Lo que significa que llamará a un método en el puntero de la clase base y que desea la implementación más derivada: este es el punto central del polimorfismo.

Ahora, si no tenía un destructor virtual y, a través del puntero a la clase base, llama al destructor y termina llamando al destructor de la clase base. En este caso, también desea que el polimorfismo funcione en su destructor, por ejemplo, al llamar a destructor en su clase base, quiere terminar llamando a destructor de su clase más derivada, no a su clase base.

class A { virtual void f() {} ~A() {} } class B : public A { void f() {} ~B() {} } A * thing = new B(); thing->f(); // calls B''s f() delete thing; // calls ~A(), not what you wanted, you wanted ~B()

tener ~ A () virtual enciende el polimorfismo

virtual ~A() {}

Así que cuando llamas ahora

delete thing;

~ B () será llamado.

Usted declararía destructores virtuales cuando diseñe la clase como una interfaz, por ejemplo, espera que se extienda o se implemente. Una buena práctica en ese caso es tener una clase de interfaz (en el sentido de interfaces de Java) con métodos virtuales y destructor virtual y luego tener clases de implementación concretas.

Puede ver que las clases STL no tienen destructores virtuales, por lo que se supone que no deben extenderse (por ejemplo, std :: vector, std :: string ...). Si extiende std :: vector y llama a destructor en la clase base a través de un puntero o referencia, definitivamente no llamará a su destructor de clase especializado, lo que puede provocar pérdidas de memoria.


De las preguntas frecuentes sobre estilo y técnica en C ++ de Stroustrup :

Entonces, ¿cuándo debo declarar un destructor virtual? Cada vez que la clase tiene al menos una función virtual. Las funciones virtuales indican que una clase debe actuar como una interfaz para las clases derivadas y, cuando lo es, un objeto de una clase derivada puede destruirse mediante un puntero a la base.

Mucha información adicional sobre cuándo tu destructor debería ser virtual en las Preguntas frecuentes de C ++ . (Gracias Stobor)

¿Qué es un miembro virtual? De las preguntas frecuentes de C ++ :

[20.1] ¿Qué es una "función miembro virtual"?

Desde una perspectiva OO, es la característica más importante de C ++: [6.9], [6.10].

Una función virtual permite que las clases derivadas reemplacen la implementación provista por la clase base. El compilador se asegura de que siempre se llame al reemplazo cuando el objeto en cuestión sea realmente de la clase derivada, incluso si se accede al objeto con un puntero base en lugar de un puntero derivado. Esto permite que los algoritmos de la clase base se reemplacen en la clase derivada, incluso si los usuarios no conocen la clase derivada.

La clase derivada puede reemplazar completamente ("anular") la función miembro de la clase base, o la clase derivada puede reemplazar ("aumentar") la función miembro de la clase base. Esto último se logra haciendo que la función de miembro de clase derivada llame a la función de miembro de clase base, si se desea.


Si va a (o incluso podría) destruir objetos de una clase derivada a través de un puntero de clase base, necesita un destructor virtual.

Tomo el enfoque de que si voy a derivar de una clase EN TODO, entonces tendrá un destructor virtual. En realidad, no hay casos en el código que escribo donde las implicaciones de rendimiento de un destructor virtual son importantes, e incluso si no es realmente necesario hoy, podría terminar necesitándolo en el futuro cuando se modifique la clase.

Básicamente: ponga virtual en todos los destructores de clase base a menos que tenga una razón buena y bien pensada para no hacerlo.

Esa es solo otra regla de oro, pero es una que le impide cometer errores posteriores.


Siempre.

A menos que esté realmente preocupado por el almacenamiento y la sobrecarga de rendimiento de una vtable, siempre la hago virtual. A menos que tenga una herramienta de análisis estático para verificar que su destructor es virtual en los casos correctos, no vale la pena cometer un error y no crear un destructor virtual cuando sea necesario.


Un objeto de clase base debe tener un destructor virtual, cuando es necesario que la clase base realice su propia limpieza. Es decir, si ha asignado recursos en la clase base, es necesario que la clase base realice la limpieza. Al declarar su destructor virtual, se garantiza que se realizará esta limpieza (suponiendo que haya escrito la limpieza correctamente).

En general, los métodos se pueden definir virtuales en una clase base, esto permitirá que las clases derivadas anulen los métodos virtuales, implementando su propia implementación específica derivada. Encuentro que esto se demuestra más claramente con un ejemplo simple. Digamos que tenemos una ''Forma'' de clase base, ahora es posible que todas las clases derivadas deban tener la capacidad de dibujar. El objeto ''Forma'' no sabrá cómo dibujar clases derivadas de él, por lo que en la clase ''Forma'' definimos una función de dibujo virtual. es decir (virtual void draw ();). Ahora, en cada clase base podemos anular esta función, implementando un código de dibujo específico (es decir, un cuadrado se dibuja de manera diferente a un círculo).