2011-07-09 14 views
12

Dal boost::/std::shared_ptr hanno il vantaggio di tipo cancellando la loro deleter, si possono fare cose belle comeÈ necessario un distruttore virtuale per la tua interfaccia, se lo memorizzi sempre in 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'); 
} 

e questo sarà correttamente eliminare tutti puntatore grazie alla deleter corretta salvati.

Se si assicura che ogni implementazione dell'interfaccia venga sempre creata con shared_ptr<Interface> (o make_shared<Interface>), è effettivamente necessario un distruttore virtual? Lo dichiarerei lo virtual in ogni caso, ma voglio solo sapere, dal momento che shared_ptr eliminerà sempre il tipo con cui è stato inizializzato (a meno che non venga fornito un altro delet personalizzato).

+1

possibile duplicato di [shared_ptr magic:)] (http://stackoverflow.com/questions/3899790/shared-ptr-magic) –

+0

@Armen: Questo non è un duplicato, non sta chiedendo come 'shared_ptr' fa ma se dovresti usare un distruttore virtuale * sapendo * che 'shared_ptr' fa quella magia. –

+1

@David: No, non lo fa. Dice che userà comunque un distruttore virtuale. Sta chiedendo se è OK non averne uno. Quindi è un duplicato –

risposta

12

sarei ancora seguo la regola comune per le classi che sono destinate ad essere derivata:

fornire o un distruttore virtuale pubblica o un distruttore non virtuale protetto

Il motivo è che si non è in grado di controllare tutti gli usi e questa semplice regola indica che il compilatore contrassegna se si prova a delete attraverso il livello sbagliato nella gerarchia. Si consideri che shared_ptr non garantisce che chiamerà il distruttore del caso, solo che chiamerà il distruttore di tipo statico che è stato utilizzato come argomento:

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

Se base ha un distruttore non virtuale pubblica e foo rendimenti un tipo che deriva da base, quindi shared_ptr non riuscirà a chiamare il distruttore corretto. Se il distruttore di base è virtuale, tutto andrà bene, se è protetto, il compilatore ti dirà che c'è un errore lì.

+0

"Lo dichiarerei comunque virtuale, [...]". :) Buon punto per non essere in grado di controllare tutti i punti di istanziazione. Tuttavia, puoi sempre fare le cose con un costruttore nominato, ma probabilmente non è così bello. – Xeo

+1

Avviso: i distruttori protetti attualmente non rispondono true per "is_nothrow_destructible :: value' anche se non lanciano un'eccezione. Per questo motivo, vorrei favorire l'opzione pubblica. –

+0

@ Howard: grazie per le informazioni su 'is_nothrow_destructible'. Sembra fare la cosa giusta. Perché dovresti lasciare che il fatto che attualmente rappresenti correttamente "non distruttibile" per una cosa non distruttibile, ti spinge a cambiare il thingy in distruttibile? –

Problemi correlati