Das Verhalten ist nicht definiert. In diesem Fall darf das dynamisch zugeordnete Objekt nur über einen Zeiger vom Typ Type1
gelöscht werden.
Erstens verletzen Sie die Aliasregeln, indem Sie den Zeiger verwenden, der von (Type2 *)p
im Ausdruck delete
erhalten wird. Es gibt eine begrenzte Anzahl von Typen, über die das Objekt, auf das von p
verwiesen wird, verwendet werden kann. Die Regeln aus C ++ 03 finden Sie in einer Antwort auf eine andere Frage . Die C ++ 11-Regeln sind ähnlich (die Unterschiede sind für die Antwort auf Ihre Frage nicht relevant).
Selbst wenn das Programm nicht gegen die strengen Aliasing-Regeln verstößt, würde es die Anforderungen des delete
-Ausdrucks verletzen. Die Spezifikation besagt (C ++ 11 §5.3.5 [expr.delete] / 3):
Wenn der statische Typ des zu löschenden Objekts sich von seinem dynamischen Typ unterscheidet, sollte der statische Typ eine Basisklasse des dynamischen Typs des zu löschenden Objekts und der Der statische Typ sollte einen virtuellen Destruktor haben oder das Verhalten ist nicht definiert.
In Ihrem Ausdruck delete
ist der statische Typ des Objekts Type2
, während der dynamische Typ Type1
ist. Die Typen sind unterschiedlich, aber der statische Typ ist keine Basisklasse des dynamischen Typs.
Das wäre eine wirklich schlechte Idee, da Sie den Compiler bitten würden, Typ2 :: ~ Type2 für einen Type1-Zeiger auszuführen, und dieser Destruktor könnte auf das Ende des Objekts verweisen.
In herkömmlichen Umgebungen wäre der eventuelle Speicher frei, weil operator delete
free
aufruft, was sich nicht interessiert, welchen Typ Sie zur Kompilierzeit aufgerufen haben. In einer nicht so konventionellen Umgebung könnte es jedoch eine Katastrophe sein.
Obwohl diese Frage von James bereits perfekt beantwortet wurde, möchte ich auf eines hinweisen:
Im richtigen C ++ - Code arbeiten Sie fast nie mit void
-Zeigern, was bedeutet, dass Ihr Code wahrscheinlich so aussehen würde:
In diesem Fall, selbst wenn% code_de einen korrekten virtuellen Konstruktor hätte, besteht immer noch ein mögliches undefiniertes Verhalten, wenn BaseType
nicht von SubType
abgeleitet wird. Common C-Style-Besetzung ist nicht sehr glückliche Wahl hier.
Aber für den Fall, dass Sie BaseType
verwenden würden, würde der Compiler das höchstwahrscheinlich nicht zulassen, wenn dynamic_cast
nicht auf ein Objekt vom polymorphen Typ zeigt. Und selbst wenn p
auf ein Objekt vom polymorphen Typ zeigt, aber p
wäre kein Basistyp von BaseType
, würde SubType
dynamic_cast
zurückgeben und Sie könnten diesen Zustand entsprechend behandeln: