Ist dieser Code legal?
class Base1 {
};
class Base2 {
public:
virtual ~Base2() {
if (!dynamic_cast<Base1*>(this))
std::cout << "aaaa" << std::endl;
}
Base2() {
}
};
class MyClass: public Base1, public Base2 {
public:
MyClass() {
}
virtual ~MyClass() {
std::cout << "bbb" << std::endl;
}
};
int main() {
MyClass s;
return 0;
}
Ich sehe beide Drucke, aber ich sollte nur einen sehen. Ich denke, die dynamische Besetzung ist falsch. Ist es möglich, einen solchen Scheck durchzuführen?
c++
polymorphism
destructor
multiple-inheritance
dynamic-cast
greywolf82
quelle
quelle
!
dynamic_cast
sich in Konstruktoren und Destruktoren nicht anders?Antworten:
Vielleicht habe ich die Lösung selbst gefunden, die Antwort ist nein, es ist nicht möglich:
Aus Punkt 6 der Dokumentation zu cppreference.com :
Siehe auch [class.cdtor] / 6 des Standards.
Da ich im Base2-Destruktor auf Base1 umwandle, ist dieses Verhalten undefiniert.
quelle
[class.cdtor]/6
, als Referenz. Sorry, nicht 5. War 5 in C ++ 17 (Entwurf N4659), sieht aus wie es/6
jetzt ist.this
ist vom Typ des Destruktors, daher sehe ich nicht, dass UB angewendet wird. Der gleiche Standardabsatz besagt jedoch, dass der am meisten abgeleitete Typ des zu zerstörenden Objekts als die Klasse des Destruktors betrachtet wird, so dass das in der anderen Antwort erläuterte Verhalten beobachtet wird.Ich stimme der Antwort von @ j6t zu, aber hier ist eine erweiterte Argumentation mit Standardreferenzen.
Das spezielle Verhalten von
dynamic_cast
Objekten, die sich im Bau und in der Zerstörung befinden, wird in [class.cdtor] / 5 des C ++ 17-Standards (endgültiger Entwurf) und in früheren Standardversionen beschrieben.Insbesondere heißt es:
Das undefinierte Verhalten gilt hier nicht, da der Operand der Ausdruck ist
this
, der trivial den Typ eines Zeigers auf die eigene Klasse des Destruktors hat, da er im Destruktor selbst erscheint.Der erste Satz besagt jedoch, dass sich der
dynamic_cast
Wille so verhält, als wäre er*this
ein am meisten abgeleitetes Objekt vom Typ,Base2
und daher kann die Umwandlung inBase1
niemals erfolgreich sein, da erBase2
nicht von abgeleitetBase1
ist unddynamic_cast<Base1*>(this)
immer einen Nullzeiger zurückgibt, was zu dem angezeigten Verhalten führt.cppreference.com gibt an, dass das undefinierte Verhalten auftritt , wenn der Zieltyp der Umwandlung nicht der Typ der Destruktorklasse oder eine ihrer Basen ist, anstatt dies auf den Operandentyp anzuwenden. Ich denke das ist nur ein Fehler. Wahrscheinlich sollte die Erwähnung von " neuem Typ " in Punkt 6 " Ausdruck " sagen , was dazu führen würde, dass es meiner obigen Interpretation entspricht.
quelle
Das
dynamic_cast
ist in dieser Situation gut definiert. Es ist richtig, dass Sie beide Ausgabezeilen beobachten.Es ist falsch anzunehmen, dass im Destruktor von
Base2
this
eine abgeleitete Klasse ist. Zu diesem Zeitpunkt wurde der abgeleitete Klassenteil bereits zerstört, sodass er keine abgeleitete Klasse mehr sein kann. Tatsächlich ist zu dem Zeitpunkt, an dem der Destruktor ausgeführt wirdBase2
, das Objekt, auf das gezeigtthis
wird, nur einBase2
Objekt. DaBase2
nicht in Bezug aufBase1
in irgendeiner Weise, diedynamic_cast
liefert einen Null - Zeiger, und die bedingten entsprechend eingegeben.Bearbeiten: Der Standard sagt :
Der Operand
this
bezieht sich auf das zu zerstörende Objekt. Daher wird die Klasse des Destruktors (Base2
) als die am meisten abgeleitete Klasse betrachtet, und dies ist der Grund, warum das ObjektBase1*
in keiner Weise mit dem Zieltyp ( ) verknüpft ist . Darüber hinaus ist die statische Typ des Operandenthis
istBase2* const
, die eindeutig ist ein Zeiger auf die eigene Klasse destructor. Daher gilt die Regel über undefiniertes Verhalten nicht. Zusammenfassend haben wir ein klar definiertes Verhalten.quelle
[class.cdtor]/6
in der anderen Antwort erwähnt, dass cppref dasselbe bedeutet: "Wenn der Operand des dynamic_cast auf das im Aufbau oder in der Zerstörung befindliche Objekt verweist und der statische Typ des Operanden kein Zeiger auf oder Objekt des Konstruktors oder ist Der Dynamic_cast ist die eigene Klasse des Destruktors oder eine seiner Basen und führt zu undefiniertem Verhalten. "