2011-07-09 10 views
12

Desde boost::/std::shared_ptr tienen la ventaja de tipo de borrado de su Deleter, se pueden hacer cosas agradables como¿Se necesita un destructor virtual para su interfaz, si siempre lo almacena en un shared_ptr?

#include <memory> 

typedef std::shared_ptr<void> gc_ptr; 

int main(){ 
    gc_ptr p1 = new int(42); 
    gc_ptr p2 = new float(3.14159); 
    gc_ptr p3 = new char('o'); 
} 

y esto va a eliminar correctamente todos puntero gracias a la Deleter correcta se salvan.

Si se asegura de que cada implementación de su interfaz siempre se crea con shared_ptr<Interface> (o make_shared<Interface>), ¿realmente necesita un destructor virtual? Lo declararía virtual de todos modos, pero solo quiero saber, ya que shared_ptr siempre eliminará el tipo con el que se inicializó (a menos que se proporcione otro eliminador personalizado).

+1

posible duplicado de [shared_ptr magic:)] (http://stackoverflow.com/questions/3899790/shared-ptr-magic) –

+0

@Armen: Esto no es un duplicado, no pregunta cómo 'shared_ptr' hace pero si debe usar un destructor virtual * sabiendo * que 'shared_ptr' hace esa magia. –

+1

@David: No, no lo hace. Él dice que usará un destructor virtual de todos modos. Él pregunta si está bien no tener uno. Entonces es un duplicado –

Respuesta

12

yo todavía sigo la regla común para las clases que están destinados a ser derivada:

proporcionen a un destructor virtual público o un destructor no virtual protegida

La razón es que se no puede controlar todos los usos, y esa regla simple significa que el compilador marcará si intenta delete a través del nivel incorrecto en la jerarquía. Tengamos en cuenta que shared_ptr no garantiza que va a llamar al destructor apropiada, sólo que se llamará al destructor del tipo estático que fue utilizado como argumento:

base* foo(); 
shared_ptr<base> p(foo()); 

Si base tiene un destructor no virtual pública y foo retornos un tipo que deriva de base, luego shared_ptr no podrá llamar al destructor correcto. Si el destructor de base es virtual, todo estará bien, si está protegido, el compilador le dirá que hay un error allí.

+0

"De todos modos declararía virtual, [...]". :) Buen punto acerca de no poder controlar todos los puntos de ejemplificación. Sin embargo, siempre se puede hacer con un constructor nombrado, pero probablemente no se vea tan bien. – Xeo

+1

Advertencia: los destructores protegidos actualmente no responden como verdaderos para 'is_nothrow_destructible :: value' incluso si no lanzan una excepción. Por eso razono que preferiría la opción pública. –

+0

@Howard: gracias por la información sobre 'is_nothrow_destructible'. Parece hacer lo correcto. ¿Por qué dejarías que el hecho de que actualmente informe correctamente "no destructible" de una cosa no destructible, te haga cambiar la cosa por destructible? –

Cuestiones relacionadas