Esistono circostanze in cui è legittimo che una classe derivata abbia un distruttore non virtuale?
Sì.
Un distruttore non virtuale indica che una classe non deve essere utilizzata come una classe base.
Non proprio; un distruttore non virtuale indica che l'eliminazione di un'istanza di derived
tramite un puntatore base
non funzionerà. Per esempio:
class Base {};
class Derived : public Base {};
Base* b = new Derived;
delete b; // Does not call Derived's destructor!
Se non fai delete
nel modo sopra, allora sarà bene. Ma se questo è il caso, probabilmente useresti la composizione e non l'ereditarietà.
Will avere un distruttore non virtuale di un atto di classe derivata come una forma debole del modificatore finale di Java?
No, perché virtual
-ness si propaga alle classi derivate.
class Base
{
public:
virtual ~Base() {}
virtual void Foo() {};
};
class Derived : public Base
{
public:
~Derived() {} // Will also be virtual
void Foo() {}; // Will also be virtual
};
Non c'è un meccanismo incorporato il linguaggio in C++ 03 o precedente per impedire sottoclassi (*). Il che non è un problema in ogni caso, dal momento che si dovrebbe sempre prefer composition over inheritance. Cioè, usa l'ereditarietà quando una relazione "è-a" ha più senso di una vera relazione "ha-a".
(*) modificatore 'finale' è stato introdotto in C++ 11
fonte
2011-09-13 14:54:43
"' virtual'-ness si propaga alle classi derivate. " Lo fa? [consulta lo standard]. 12.4.7: "Se una classe ha una classe base con un distruttore virtuale, il suo distruttore (se dichiarato dall'utente o implicitamente) è virtuale. – Raedwald
Su una nota correlata, se si ha una classe Base non virtuale, e hai alcuni metodi virtuali nella tua classe derivata, quindi 'Base * b = new Derived(); delete b;' sarà un comportamento indefinito e probabilmente bloccherà il tuo programma. Sembra abbastanza sicuro, ma non lo è. (È perché 'b 'non punta al 'inizio' dell'oggetto' Derivato' - sarà compensato dallo spazio necessario per il vtable, quindi 'delete' non opererà esattamente sullo stesso indirizzo di' new', e quindi non è un indirizzo valido da liberare Se hai intenzione di avere metodi virtuali da qualche parte, allora metti un virtual dator nella base: –