Aufruf der virtuellen Funktion von Destruktor
Ist dies sicher ?
class Derived: public PublicBase, private PrivateBase
{
...
~Derived()
{
FunctionCall();
}
virtual void FunctionCall()
{
PrivateBase::FunctionCall();
}
}
class PublicBase
{
virtual ~PublicBase(){};
virtual void FunctionCall() = 0;
}
class PrivateBase
{
virtual ~PrivateBase(){};
virtual void FunctionCall()
{
....
}
}
PublicBase* ptrBase = new Derived();
delete ptrBase;
Dieser code crases manchmal mit der IP schlechte Adresse.
Dass ist keine gute Idee, aufrufen einer virtuellen Funktion auf der Konstruktor ist klar.
Aus Artikeln wie http://www.artima.com/cppsource/nevercall.html ich verstehen, dass der Destruktor ist auch ein nicht so guter Ort zum aufrufen einer virtuellen Funktion.
Meine Frage ist: "ist dies wahr ?" Ich habe getestet mit VS2010 und VS2005 und PrivateBase::Funktionsaufruf aufgerufen wird. Ist Undefiniertes Verhalten ?
InformationsquelleAutor der Frage cprogrammer | 2012-08-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Werde ich gegen den Strom hier... aber zuerst, muss ich annehmen, dass Ihr
PublicBase
Destruktor virtuell ist, da sonst dieDerived
Destruktor nie aufgerufen.Es ist in der Regel nicht eine gute Idee, rufen eine virtuelle Funktion von einem Konstruktor/Destruktor
Der Grund dafür ist, dass die dynamic dispatch ist seltsam, während dieser beiden Operationen. Der tatsächliche Typ des Objekts änderungen während der Bau-und it - änderungen wieder während der Zerstörung. Wenn ein Destruktor ausgeführt wird, wird das Objekt von genau diesem Typ, und nie eine Art daraus abgeleitet. Dynamic dispatch in Kraft ist, zu aller Zeit, aber die final overrider der virtuellen Funktion wird sich ändern, je nachdem, wo in der Hierarchie Sie stehen.
Ist, sollte man niemals erwarten, dass ein Aufruf einer virtuellen Funktion in einem Konstruktor/Destruktor ausgeführt werden, in jeder Art, abgeleitet aus dem Typ des Konstruktor/Destruktor ausgeführt wird.
Aber
In Ihrem speziellen Fall, die letzten overrider (zumindest für diesen Teil der Hierarchie) ist oben Ihrem Niveau. Darüber hinaus sind Sie nicht mit dynamic dispatch überhaupt. Der Aufruf
PrivateBase::FunctionCall();
ist statisch gelöst werden, und Sie effektiv äquivalent zu einem Aufruf an alle nicht-virtuellen Funktion. Die Tatsache, dass die Funktion virtuellen oder nicht, berührt nicht diesen Anruf.So ja es ist in Ordnung zu tun, wie Sie tun, obwohl Sie gezwungen werden, zu erklären, diese in code-reviews, wie die meisten Menschen lernen das mantra eher die Regel als der Grund dafür.
InformationsquelleAutor der Antwort David Rodríguez - dribeas
Ja. Aufruf einer virtuellen Funktion vom Konstruktor oder Destruktor löst die Funktion aus, als wenn das Objekt den dynamischen Typ waren, die derzeit gebaut oder zerstört werden. In diesem Fall ist es der Aufruf von Destruktor
Derived
so ist es geschicktDerived::FunctionCall
(die, in Ihrem Fall, fordertPrivateBase::FunctionCall
non-virtuell). All dies ist sehr gut definiert.Es ist "keine gute Idee" zu nennen, virtuelle Funktionen, die von einem Konstruktor oder Destruktor aus drei Gründen:
InformationsquelleAutor der Antwort Mike Seymour
Im Allgemeinen ist es nicht eine gute Idee zum aufrufen einer virtuellen Funktion, es sei denn, das Objekt der Klasse könnte es ausgelöst wurde (D. H., die "volle" Objekt der am meisten abgeleiteten Klasse) ist vollständig konstruiert. Und dies ist nicht der Fall
InformationsquelleAutor der Antwort Grzegorz Herman
Es ist eine sehr schlechte Idee, nach scott: link
Dies ist, was ich zusammengestellt haben, und laufen, um mir selbst helfen zu gewinnen ein besseres Verständnis von der Zerstörung Prozess, Sie finden es vielleicht auch hilfreich
InformationsquelleAutor der Antwort sji