2010-07-26 22 views
8

tengodesctructor puro virtual en la clase base abstracta

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
}; 

GCC insiste en que tengo

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
    virtual ~IMyInterface(){}; 
}; 

no veo por qué. Una interfaz pura se trata de la interfaz (duh). El destructor es parte de los detalles de implementación interna de un implementador concreto de la interfaz; no forma parte de la interfaz. Entiendo todo el problema del corte (o al menos creo que sí)

Así que mi pregunta es: ¿es correcto que GCC insista y, en caso afirmativo, por qué?

+0

Usted está hablando de destructores, pero su código muestra un constructor. ¿De qué se trata la pregunta? –

+0

@mmyers, lo arreglaron. –

+1

Regla 1 de Programación: El compilador siempre tiene la razón. Regla 2 de la Programación: Si el Compilador es Incorrecto, se aplica la Regla 1. –

Respuesta

19

De acuerdo con la especificación C++, sí.

tiene que declarar el destructor virtual, porque de lo contrario, tarde

IMyInterface * ptr = getARealOne(); 
    delete ptr; 

no llamará al destructor de la clase derivada (debido a que el destructor no está en la viable)

que necesita para ser no puro porque los destructores de la clase base siempre son llamados por el destructor de subclase.

Para explicar mejor, C++ no tiene un concepto de interfaz del mismo modo que Java o C#. Es solo una convención usar solo métodos puramente virtuales, y pensar en eso como una interfaz. Las otras reglas sobre los destructores de C++ hacen que sea necesario que no sean puras, lo que rompe la similitud con las interfaces en otros idiomas, pero esos idiomas no existían en el momento en que se hicieron estas reglas.

+4

Nitpick: creo que puedes hacerlo puramente virtual si quieres requerir clases para niños para implementarlo. Pero aún debe proporcionar una implementación por las razones que indicó. –

+0

No lo creo, se llamará, por lo que es mejor tener una definición. No lo he probado, pero el compilador implementa virtualmente un pure-virtual como si pusiera una función de error en la tabla VT para quejarse de que se había invocado. Tal vez podría imaginar un caso especial para los destructores, pero estoy bastante seguro de que eso no es lo que dice la especificación (aunque no al 100%) –

+0

@Lou Franco: las funciones virtuales puras pueden tener definiciones. –

3

Si no declara el campo virtual en la clase base, eliminar objetos de clases derivadas a través de un puntero a la clase base conduce a la invocación del destructor incorrecto y, por lo tanto, a un comportamiento indefinido y pérdida de recursos.

struct A { 

    virtual ~A() {} 

}; 

struct B : A { 

    std::string us_constitution; 
}; 


B* pb = new B(); 
A* pa = pb; 

delete pa; // without the virtual d'tor in the base class, 'B::us_constitution' would never be freed. 
+0

Nitpick: B :: us_constitution no se puede liberar porque nunca se ha renovado. Sin embargo, el almacenamiento que utiliza no se devolverá al sistema sin el destructor virtual. –

Cuestiones relacionadas