dynamic_cast
conversion
Konvertiert sicher Zeiger und Referenzen auf Klassen aufwärts, abwärts und seitwärts entlang der Vererbungshierarchie.
Inhaltsverzeichnis |
Syntax
dynamic_cast<
Zieltyp
>(
Ausdruck
)
|
|||||||||
| target-type | - | Zeiger auf vollständigen Klassentyp, Referenz auf vollständigen Klassentyp oder Zeiger auf (optional cv-qualifizierten) void |
| expression | - | Lvalue (bis C++11) Glvalue (seit C++11) eines vollständigen Klassentyps, wenn target-type eine Referenz ist; Prvalue eines Zeigers auf vollständigen Klassentyp, wenn target-type ein Zeiger ist |
Erklärung
Zur Vereinfachung der Beschreibung bedeutet „
expression
oder das Ergebnis ist eine Referenz auf
T
“, dass „es ein Glvalue vom Typ
T
ist“
, was der Konvention von
decltype
(seit C++11)
folgt.
Nur die folgenden Konvertierungen können mit dynamic_cast durchgeführt werden, außer wenn solche Konvertierungen Constness entfernen würden (oder Volatilität).
Base
" ist und der Typ von
expression
"Zeiger auf (möglicherweise cv-qualifiziertes)
Derived
" ist, sodass
Base
eine Basisklasse von
Derived
ist, dann ist das Ergebnis
- ein Nullzeigerwert, wenn expression ein Nullzeigerwert ist, oder
-
ein Zeiger auf das eindeutige
BaseSubobjekt desDerived-Objekts, auf das expression zeigt, andernfalls. Mit anderen Worten, dynamic_cast kann verwendet werden, um Zeiger upzucasten , von abgeleitet zu basis. Eine implizite Konvertierung und static_cast können diese Konvertierung ebenfalls durchführen.
Base
" ist und der Typ von
expression
"(möglicherweise cv-qualifiziertes)
Derived
" ist, sodass
Base
eine Basisklasse von
Derived
ist, dann ist das Ergebnis das eindeutige
Base
-Subobjekt des
Derived
-Objekts, auf das durch
expression
verwiesen wird. Mit anderen Worten kann
dynamic_cast
verwendet werden, um Referenzen
upzucasten
, von abgeleiteter zu Basisklasse. Eine implizite Konvertierung und
static_cast
können diese Konvertierung ebenfalls durchführen.
Target
konvertiert werden kann, auf den/das durch
target-type
gezeigt/verwiesen wird:
Target
-Objekts zeigt/verweist, und wenn nur ein Objekt vom Typ
Target
von dem Subobjekt abgeleitet ist, auf das/das durch
expression
gezeigt/verwiesen wird, zeigt/verweist das Ergebnis auf dieses
Target
-Objekt. Mit anderen Worten,
dynamic_cast
kann verwendet werden, um Zeiger/Referenzen
abwärts zu konvertieren
, von Basis zu abgeleitet.
Target
besitzt, zeigt/verweist das Ergebnis auf das
Target
-Subobjekt des vollständig abgeleiteten Objekts. Mit anderen Worten,
dynamic_cast
kann verwendet werden, um
Crosscasting
(oder Side-Casting) von Zeigern/Referenzen zwischen zwei Typen durchzuführen, die von derselben Basis abgeleitet sind.
- Wenn target-type ein Zeigertyp ist, ist das Ergebnis der Nullzeigerwert von target-type .
- Wenn target-type ein Referenztyp ist, wird eine Ausnahme eines Typs ausgelöst, der zu einem Handler vom Typ std::bad_cast passen würde.
Wenn dynamic_cast in einem Konstruktor oder Destruktor verwendet wird (direkt oder indirekt) und expression auf das Objekt verweist, das sich gerade im Konstruktions-/Destruktionsprozess befindet, wird das Objekt als das am stärksten abgeleitete Objekt betrachtet. Wenn target-type kein Zeiger oder keine Referenz auf die eigene Klasse des Konstruktors/Destruktors oder eine seiner Basisklassen ist, ist das Verhalten undefiniert.
Ähnlich wie bei anderen Umwandlungsausdrücken ist das Ergebnis:
|
(bis C++11) |
|
(seit C++11) |
Hinweise
Ein Downcast kann auch mit
static_cast
durchgeführt werden, was die Kosten der Laufzeitprüfung vermeidet, aber nur sicher ist, wenn das Programm garantieren kann (durch andere Logik), dass das Objekt, auf das
expression
zeigt, definitiv
Derived
ist.
Einige Formen von dynamic_cast basieren auf Laufzeit-Typinformation (RTTI), also Informationen über jede polymorphe Klasse im kompilierten Programm. Compiler bieten typischerweise Optionen zum Deaktivieren der Einbindung dieser Informationen.
Schlüsselwörter
Beispiel
#include <iostream> struct V { virtual void f() {} // muss polymorph sein, um dynamische Typumwandlung zur Laufzeit zu verwenden }; struct A : virtual V {}; struct B : virtual V { B(V* v, A* a) { // Typumwandlungen während der Konstruktion (siehe Aufruf im Konstruktor von D unten) dynamic_cast<B*>(v); // wohldefiniert: v vom Typ V*, V Basis von B, ergibt B* dynamic_cast<B*>(a); // undefiniertes Verhalten: a hat Typ A*, A keine Basis von B } }; struct D : A, B { D() : B(static_cast<A*>(this), this) {} }; struct Base { virtual ~Base() {} }; struct Derived : Base { virtual void name() {} }; int main() { D d; // das am meisten abgeleitete Objekt A& a = d; // Upcast, dynamic_cast könnte verwendet werden, aber unnötig [[maybe_unused]] D& new_d = dynamic_cast<D&>(a); // Downcast [[maybe_unused]] B& new_b = dynamic_cast<B&>(a); // Sidecast Base* b1 = new Base; if (Derived* d = dynamic_cast<Derived*>(b1); d != nullptr) { std::cout << "downcast from b1 to d successful\n"; d->name(); // sicher aufzurufen } Base* b2 = new Derived; if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr) { std::cout << "downcast from b2 to d successful\n"; d->name(); // sicher aufzurufen } delete b1; delete b2; }
Ausgabe:
downcast from b2 to d successful
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 1269 | C++11 |
die Laufzeitprüfung wurde nicht für xvalue
expression s durchgeführt, wenn target-type ein Rvalue-Referenztyp ist |
durchgeführt |
| CWG 2861 | C++98 | expression könnte auf ein typunzugängliches Objekt zeigen/verweisen | das Verhalten ist in diesem Fall undefiniert |
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 7.6.1.7 Dynamic cast [expr.dynamic.cast]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 7.6.1.6 Dynamic cast [expr.dynamic.cast]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 8.2.7 Dynamic cast [expr.dynamic.cast]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++11-Standard (ISO/IEC 14882:2011):
-
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++98 Standard (ISO/IEC 14882:1998):
-
- 5.2.7 Dynamic cast [expr.dynamic.cast]
- C++03-Standard (ISO/IEC 14882:2003):
-
- 5.2.7 Dynamic cast [expr.dynamic.cast]