Da ich nicht sehe, wie virtuelle Funktionen die Zerstörungsreihenfolge von Objekten ändern, nehme ich an, dass Sie sich auf die Reihenfolge der Zerstörung für Basisklassen und Datenelemente in einer virtuellen Vererbung beziehen Szenario.
Unterobjekte sind konstruiert
Destruction ist einfach das Gegenteil von construction , also müssen Sie sich nur das oben genannte merken.
Aber die obigen vier Regeln sind in dieser Reihenfolge, weil das Sinn macht, und wenn Sie verstehen, warum diese Reihenfolge sinnvoll ist, werden Sie diese vier Regeln nicht einmal auswendig lernen müssen, sondern können sie aus Ihrem Verständnis ableiten (wie ich gerade tat). Sehen wir uns diese Reihenfolge an:Angenommen, Sie haben Ihren Destruktor korrekt als virtuell deklariert.
Dann erfolgt die Zerstörung in genau umgekehrter Reihenfolge der Konstruktion.
A) Beginnen Sie in der abgeleiteten Klasse.
B) Wiederhole das Folgende rekursiv.
1) Führen Sie den Destruktorcode aus.
2) Führe den Destruktor jedes Mitglieds (in umgekehrter Reihenfolge der Erstellung) aus
3) Führen Sie den Destruktor der Elternklasse aus. (wenn mehr als eins in umgekehrter Reihenfolge der Erstellung)
Wenn Sie die virtuelle Vererbung verwenden, dann sind die Dinge etwas anders, da die Reihenfolge der Basisklassenkonstruktionen nicht mit der normalen übereinstimmt. ABER Die Reihenfolge der Zerstörung ist IMMER das Gegenteil der Reihenfolge der Konstruktion.
Die Zerstörungsreihenfolge ist die Konstruktionsreihenfolge rückwärts. Ich habe kürzlich ein kleines Tool erstellt, um die Konstruktionsreihenfolge für jede Hierarchie anzuzeigen. Schau hier:
In den Diagrammen werden die Knoten mit den kleineren Zahlen zuerst und zuletzt zerstört.
Abschnitt 12.6.2 / 5:
Die Initialisierung wird in der folgenden Reihenfolge durchgeführt:
- Zuerst und nur für den Konstruktor der abgeleiteten Klasse as Wie unten beschrieben, sollen virtuelle Basisklassen in der Reihenfolge erscheinen sie auf einer Tiefe-zuerst von links nach rechts Durchquerung der gerichtetes azyklisches Diagramm der Basisklassen, wobei "von links nach rechts" das ist Reihenfolge des Auftretens der Basisklassennamen in der abgeleiteten Klasse Base-Specifier-Liste.
- Dann sollen direkte Basisklassen initialisiert werden in der Deklarationsreihenfolge, wie sie in der Basisspezifiziererliste erscheinen (unabhängig von der Reihenfolge der Mem-Initialisierer).
- Dann, nicht statisch Datenelemente werden in der Reihenfolge initialisiert, in der sie deklariert wurden die Klassendefinition (wiederum unabhängig von der Reihenfolge der mem-Initialisierer). - Schließlich wird der Rumpf des Konstruktors ausgeführt.
[Hinweis: Die Deklarationsreihenfolge ist vorgeschrieben, um sicherzustellen, dass die Basis und die Teilobjekte werden in umgekehrter Reihenfolge zerstört Initialisierung. ]
Reihenfolge der Zerstörungen, wenn von unten nach oben. (von abgeleiteten zur Basis)
Kurze Antwort: das genaue Gegenteil von die Konstruktorreihenfolge.
Lange Antwort: Angenommen, die meisten abgeleitet "Klasse ist D, was bedeutet tatsächliches Objekt, das ursprünglich war erstellt wurde von Klasse D, und das D erbt multipliziert (und nicht virtuell) von B1 und B2. Das Unterobjekt entspricht der am meisten abgeleiteten Klasse D läuft zuerst, gefolgt von den dtors für seine nicht virtuellen Basisklassen in umgekehrte Deklarationsreihenfolge Und so kam es dass der Destruktorreihenfolge ist D, B2, B1. Diese Regel wird rekursiv angewendet. zum Beispiel, wenn B1 von B1a und B1b und B2 erbt von B2a und B2b, die letzte Reihenfolge ist D, B2, B2b, B2a, B1, B1b, B1a.
Siehe c ++ faq-Abschnitt 25
Virtuelle Funktionen machen keinen Unterschied in der Reihenfolge der Zerstörung, virtuelle Basisklassen andererseits.
Ohne virtuelle Basisklassen werden abgeleitete Klassen immer vor ihren Basisklassen zerstört; Dies ist die umgekehrte Reihenfolge, in der sie konstruiert sind.
Für die am weitesten abgeleitete Klasse werden virtuelle Basisklassen zuerst vor anderen Basisklassen und vor der am weitesten abgeleiteten Klasse selbst erstellt. Die Zerstörung geschieht in umgekehrter Reihenfolge. Dies bedeutet, dass eine virtuelle Basis nach einer Klasse, die virtuell von ihr abgeleitet ist, zerstört werden kann, wenn diese Klasse nicht die am weitesten abgeleitete Klasse ist, die zerstört wird. Dies kann niemals für direkte Basisklassen passieren.
Zuerst die abgeleitete, dann die Basis. Kein Unterschied zu den nicht-virtuellen Fällen.
Zusätzliche Anmerkung. Wenn Sie Vererbungs- und virtuelle Methoden verwenden, müssen Sie Destruktoren als virtuell deklarieren, andernfalls können Sie beim Löschen undefiniertes Verhalten haben.
Beispiel: Angenommen, Derived wird von Base abgeleitet, und Sie ordnen Derived mit der folgenden Zeile zu:
%Vor%Wenn dieser Fall in Ihrem Code auftritt und Base keinen virtuellen Destruktor hat, ist das resultierende Verhalten nicht definiert. Normalerweise wird nur der Destruktor von Base aufgerufen. Der Destruktor von Derived wird nicht aufgerufen, da Sie delete für einen Basiszeiger aufrufen. Das Programm stürzt jedoch möglicherweise ab. Sobald Sie sich im Bereich des undefinierten Verhaltens befinden, sind alle Wetten deaktiviert und Ihr Ausführungscode ist zum Scheitern verurteilt. Um Chaos zu vermeiden, muss der Base-Destruktor virtuell sein.
Tags und Links c++ destructor virtual-destructor