que programación programacion porque poo orientado orientada objetos lenguaje introduccion enlace dinamico destructores constructores con caracteristicas c++ inheritance virtual-destructor

c++ - programación - ¿Se heredan los destructores virtuales?



porque se dice que c++ es un lenguaje orientado a objetos (4)

Si tengo una clase base con un destructor virtual. Tiene una clase derivada para declarar un destructor virtual también?

class base { public: virtual ~base () {} }; class derived : base { public: virtual ~derived () {} // 1) ~derived () {} // 2) };

Preguntas concretas:

  1. Es 1) y 2) lo mismo? ¿Es 2) automáticamente virtual debido a su base o "detiene" la virtualidad?
  2. ¿Se puede omitir el destructor derivado si no tiene nada que hacer?
  3. ¿Cuál es la mejor práctica para declarar el destructor derivado? ¿Declararlo virtual, no virtual u omitirlo si es posible?

  1. El destructor es automáticamente virtual, como con todos los métodos. No se puede evitar que un método sea virtual en C ++ (si ya se ha declarado virtual, es decir, es decir, no hay un equivalente de ''final'' en Java)
  2. Sí, se puede omitir.
  3. Declararía un destructor virtual si pretendo que se subclasifique esta clase, no importa si está subclasificando otra clase o no, también prefiero seguir declarando métodos virtuales, aunque no sean necesarios. Esto mantendrá las subclases funcionando, en caso de que alguna vez decida eliminar la herencia. Pero supongo que esto es solo una cuestión de estilo.

  1. Sí, son lo mismo. La clase derivada que no declara algo virtual no impide que sea virtual. De hecho, no hay forma de evitar que un método (destructor incluido) sea virtual en una clase derivada si fue virtual en una clase base. En> = C ++ 11 puede usar el final para evitar que se anule en clases derivadas, pero eso no impide que sea virtual.
  2. Sí, un destructor en una clase derivada se puede omitir si no tiene nada que hacer. Y no importa si es virtual o no.
  3. Yo lo omitiría si fuera posible. Y siempre utilizo la palabra clave virtual nuevamente para funciones virtuales en clases derivadas por razones de claridad. La gente no debería tener que recorrer todo el camino de la jerarquía de herencia para descubrir que una función es virtual. Además, si su clase se puede copiar o mover sin tener que declarar su propia copia o mover constructores, declarar un destructor de cualquier tipo (incluso si lo define como default ) lo obligará a declarar la copia y mover constructores y operadores de asignación si los quiero porque el compilador ya no los pondrá por ti.

Como un pequeño punto para el ítem 3. Se ha señalado en los comentarios que si un destructor no está declarado, el compilador genera uno por defecto (que aún es virtual). Y esa predeterminada es una función en línea.

Las funciones en línea exponen potencialmente más de su programa a cambios en otras partes de su programa y dificultan la compatibilidad binaria para bibliotecas compartidas. Además, el aumento de acoplamiento puede dar lugar a una gran cantidad de recompilación frente a ciertos tipos de cambios. Por ejemplo, si decide que realmente desea una implementación para su destructor virtual, entonces cada parte del código que lo llamó tendrá que ser recompilado. Mientras que si lo hubiera declarado en el cuerpo de la clase y luego lo hubiera definido vacío en un archivo .cpp , estaría bien cambiarlo sin volver a compilar.

Mi elección personal sería omitirla cuando sea posible. En mi opinión, complica el código, y el compilador a veces puede hacer cosas ligeramente más eficientes con una implementación predeterminada que con una vacía. Pero existen restricciones en las que puede estar inmerso que hacen que esa sea una mala elección.


1 / Sí 2 / Sí, será generado por el compilador 3 / La elección entre declararlo virtual o no debe seguir su convención para los miembros virtuales anulados - en mi humilde opinión, hay buenos argumentos en ambos sentidos, simplemente elija uno y sígalo.

Lo omitiría si fuera posible, pero hay una cosa que puede incitarlo a declararlo: si usa el compilador generado, está implícitamente en línea. Hay momentos en los que desea evitar miembros en línea (bibliotecas dinámicas, por ejemplo).


Una función de miembro virtual hará implícitamente cualquier sobrecarga de esta función virtual.

Entonces, el virtual en 1) es "opcional", el destructor de la clase base que es virtual hace que todos los destructores secundarios sean virtuales también.