0

Ich habe einige Artikel gelesen, und wie sie sagen, virtuellen Haupt destructor Anwendungsfälle sind:Virtuelle destructor Use Cases

  • abgeleitet Klassen dynamische Datenzuordnung von Heap haben kann, dh ‚eigene‘, dass Datenobjekt. Sie brauchen also eine Löschroutine im Destruktor. Deletion durch Basisklassenzeiger erfordert virtual Erklärung Destruktoren in allen abgeleiteten Klasse bis die mit dynamischen Datenzuordnung ( Basisklasse auch erfordert)

  • Diese Klasse hat virtual Methoden. Aber das ist mir unklar. Ruft einfach virtual Methoden durch Basis Klassenzeiger führt immer zu den meisten abgeleiteten -Realisierungsaufrufe. Der einzige Ausschluss für diese Regel ist die Bauphase. Literaly, während es this Objekt ist kein abgeleitet Typ noch, auch wenn später sein wird. Ok, was ist mit der Zerstörungsphase? Wie ich verstanden habe, ist die Regel in der umgekehrten Reihenfolge. Egal, war Destruktor einer Klasse in der Hierarchie als virtual deklariert, während jeder Destruktor this Zeiger als ob dieser Klasse Typ verwendet wurde, wurden alle abgeleiteten wurden bereits zerstört wegen virtual dr, oder nicht zerstört (und das kann hypothetisch in Ordnung sein etwas Design). Vielleicht ist das der Fall, warum muss d-r virtuell sein? Vtable wird Einträge für abgeleitete Klasse haben, und Aufruf virtual Methoden in einigen Basis Klasse von d-r wird in UB führen? Ok, aber diese Regel gilt nur für den Fall, wenn diese Klasse ruft einige virtual Methoden in d-r, und sie haben Realisierung in abgeleitet Klassen.

meiner Meinung nach, dass es auch einen Fall ohne dynamische Datenzuordnung kann ist, keine virtuellen Methoden in allen Hierarchie, aber immer noch abgeleitet Destruktoren können einige wichtige Aufgaben beim Löschen tun (Synchronisierungen, entriegelt und so weiter) . Und wir brauchen virtuelles d-r in der Basisklasse. Mag sein, dass solche Fälle Ergebnisse von schlechtem Design sind.

Wie auch immer, Entwickler einer öffentlichen Klasse kann nicht 100% wissen, ob abgeleitete Klassen einige virtuelle Methoden in d-r verwenden oder nicht, oder dynamische Daten zuweisen. Also, muss ich richtig sagen, dass jede öffentliche Klasse, die nicht als final deklariert ist, d-r als virtuell deklarieren muss? Nur das Schlüsselwort final garantiert, dass jeder Zeiger auf diese Klasse immer von diesem Typ ist und daher nicht-virtuell sicher gelöscht werden kann.

+1

Verwandte: http://www.gotw.ca/publications/mill18.htm – SingerOfTheFall

+0

NO. Was die Klasse selbst intern tut oder enthält, ist völlig irrelevant. Das einzige Kriterium ist, wie es verwendet wird.Wenn ein abgeleitetes Klassenobjekt über einen Basiszeiger gelöscht werden soll, muss die Basisklasse über einen virtuellen Destruktor verfügen. Nicht mehr, nicht weniger. –

+0

Entwickler können sich jedoch nicht sicher sein, ob der Basisklassenzeiger als Zeiger auf die abgeleitete Klasse verwendet wird, den andere Entwickler verwenden und auf diese Weise verwenden. Daher sollte der Entwickler der Basisklasse d-r als virtuell deklarieren. Oder es gibt eine Chance von UB. –

Antwort

3

Wenn ein abgeleitetes Objekt über einen Zeiger auf die Basisklasse gelöscht wird, muss (und nur dann) der Basisklassendestruktor virtuell sein. Ansonsten ist es undefined behaviour. Es gibt keine anderen relevanten Regeln.

Wenn die Klasse trotzdem eine virtuelle Funktion hat, wird kein Overhead eingeführt. Wenn die Klasse keine anderen virtuellen Funktionen hat, muss der Designer der Basisklasse den Trade zwischen dem Hinzufügen der Laufzeitstrafe eines virtuellen Destruktors und dem Risiko berücksichtigen, dass ein Benutzer der Klasse versuchen könnte, ein abgeleitetes Objekt über die Klasse zu löschen Basisklassenzeiger.

Here is a link to a similar discussion, with Standard quotes

+0

Ok danke, sehe ich jetzt. Also, mein Vorschlag war hauptsächlich richtig, der Entwickler entscheidet, basierend auf der Hoffnung, dass ein Benutzer ein guter Benutzer ist oder nicht –

+0

@ ЯрикЗюлин oder umgekehrt sollte der Benutzer untersuchen, ob die Klasse einen virtuellen Destruktor hat, bevor zu versuchen, von abzuleiten es und verwenden Sie einen Basisklassenzeiger (was wahrscheinlich eine schlechte Idee ist, gibt es keinen Grund, dies zu tun, wenn es keine virtuellen Funktionen gibt) –

+0

Und wenn Designer Basisklasse Zeiger beim Löschen verwendet, hat aber nicht-virtuellen dr - dies implizit sagt, dass diese Basisklasse überhaupt nicht als Basisklasse verwendet werden soll, ja? –