¿Se heredan los destructores virtuales?


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 ver?
  3. ¿Cuál es la mejor práctica para declarar el destructor derivado? ¿Declararlo virtual, no virtual u omitirlo si es posible?
Author: Melebius, 2010-02-04

4 answers

  1. Sí, son lo mismo. La clase derivada que no declara algo virtual no impide que sea virtual. De hecho, no hay manera de detener cualquier método (destructor incluido) de ser virtual en una clase derivada si era virtual en una clase base. En > = C++11 puede usar final para evitar que se anule en clases derivadas, pero eso no impide que sea virtual.
  2. Sí, un destructor en una clase derivada puede ser omitido si no tiene nada que ver. Y no importa si es virtual o no.
  3. Lo omitiría si fuera posible. Y siempre uso la palabra clave virtual de nuevo para funciones virtuales en clases derivadas por razones de claridad. La gente no debería tener que ir todo el camino hasta la jerarquía de herencia para averiguar que una función es virtual. Además, si su clase es copiable o móvil sin tener que declarar sus propios constructores de copia o movimiento, declarar un destructor de cualquier tipo (incluso si lo define como default) lo obligará a para declarar los constructores de copia y movimiento y los operadores de asignación si los desea como compilador ya no los pondrá por usted.

Como pequeño punto para el tema 3. Se ha señalado en comentarios que si un destructor no es declarado el compilador genera uno por defecto (que sigue siendo virtual). Y que por defecto es una función en línea.

Las funciones en línea potencialmente exponen más de su programa a cambios en otras partes de su programa y hacen binario compatibilidad para bibliotecas compartidas complicado. Además, el aumento del acoplamiento puede resultar en 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 pieza de código que lo llamó tendrá que ser recompilada. 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 recompilarlo.

Mi elección personal todavía debe omitirlo cuando sea posible. En mi opinión, estorba el código, y el compilador a veces puede hacer cosas un poco más eficientes con una implementación predeterminada sobre una vacía. Pero hay restricciones bajo las que puede estar que hacen que sea una mala elección.

 85
Author: Omnifarious,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-18 16:26:48

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

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

 1
Author: Klaim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-04 09:04:25
  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, no hay equivalente a 'final' en Java)
  2. Sí se puede omitir.
  3. Declararía un destructor virtual si tengo la intención de que esta clase sea subclasificada, no importa si está subclasificando otra clase o no, también prefiero seguir declarando métodos virtuales, aunque no sea necesario. Esto mantendrá subclases de trabajo, si alguna vez decide eliminar la herencia. Pero supongo que esto es sólo una cuestión de estilo.
 1
Author: falstro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-04 09:06:40

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 IM En mi humilde opinión, hay buenos argumentos en ambos sentidos, solo tiene que elegir uno y seguirlo.

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

 0
Author: AProgrammer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-04 09:07:55