dynamic_cast-Konvertierung
Konvertiert sicher Zeiger und Referenzen auf Klassen nach oben, unten und seitwärts in der Vererbungshierarchie.
Inhalt |
[bearbeiten] Syntax
dynamic_cast< Zieltyp >( Ausdruck ) |
|||||||||
| Zieltyp | - | Zeiger auf einen vollständigen Klassentyp, Referenz auf einen vollständigen Klassentyp oder Zeiger auf void (optional cv-qualifiziert) |
| expression | - | lvalue(bis C++11)glvalue(seit C++11) eines vollständigen Klassentyps, wenn Zieltyp eine Referenz ist, prvalue eines Zeigers auf einen vollständigen Klassentyp, wenn Zieltyp ein Zeiger ist. |
[bearbeiten] Erklärung
Zur Vereinfachung der Beschreibung bedeutet „Ausdruck oder das Ergebnis ist eine Referenz auf T“, dass „es sich um einen glvalue vom Typ T handelt“, was der Konvention von decltype folgt.(seit C++11)
Nur die folgenden Konvertierungen können mit dynamic_cast durchgeführt werden, außer wenn solche Konvertierungen constness (oder Volatilität) aufheben würden.
Base“ ist und der Typ von Ausdruck „Zeiger auf (möglicherweise cv-qualifiziertes) Derived“ ist, wobei Base eine Basisklasse von Derived ist, dann ist das Ergebnis- ein Nullzeigerwert, wenn Ausdruck ein Nullzeigerwert ist, oder
- ein Zeiger auf das eindeutige
BaseUnterobjekt desDerived-Objekts, auf das von Ausdruck gezeigt wird, andernfalls. Mit anderen Worten, dynamic_cast kann verwendet werden, um Zeiger hochzukonvertieren (von abgeleitet zu Basis). Eine implizite Konvertierung und static_cast können diese Konvertierung ebenfalls durchführen.
Base“ ist und der Typ von Ausdruck „(möglicherweise cv-qualifiziertes) Derived“ ist, wobei Base eine Basisklasse von Derived ist, dann ist das Ergebnis das eindeutige Base-Unterobjekt des Derived-Objekts, auf das von Ausdruck verwiesen wird. Mit anderen Worten, dynamic_cast kann verwendet werden, um Referenzen hochzukonvertieren (von abgeleitet zu Basis). Eine implizite Konvertierung und static_cast können diese Konvertierung ebenfalls durchführen.Target konvertiert werden kann, auf den Zieltyp zeigt oder verweist.Target-Objekts zeigt/verweist und wenn nur ein Objekt vom Typ Target von dem Unterobjekt abgeleitet ist, auf das von Ausdruck gezeigt oder verwiesen wird, dann 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 hat, dann zeigt/verweist das Ergebnis auf das Target-Unterobjekt des am weitesten abgeleiteten Objekts. Mit anderen Worten, dynamic_cast kann verwendet werden, um Zeiger/Referenzen seitwärts zu konvertieren (oder quer zu konvertieren), zwischen zwei Typen, die von derselben Basis abgeleitet sind.- Wenn Zieltyp ein Zeigertyp ist, ist das Ergebnis der Nullzeigerwert von Zieltyp.
- Wenn Zieltyp ein Referenztyp ist, wird eine Ausnahme vom Typ, die mit einem Handler vom Typ std::bad_cast übereinstimmen würde, ausgelöst.
Wenn dynamic_cast in einem Konstruktor oder Destruktor (direkt oder indirekt) verwendet wird und Ausdruck auf das aktuell konstruierte/zerstörte Objekt verweist, wird das Objekt als das am weitesten abgeleitete Objekt betrachtet. Wenn Zieltyp kein Zeiger oder keine Referenz auf die eigene Klasse des Konstruktors/Destruktors oder eine ihrer Basisklassen ist, ist das Verhalten undefiniert.
Ähnlich wie bei anderen Cast-Ausdrücken ist das Ergebnis
|
(bis C++11) |
|
(seit C++11) |
[bearbeiten] Hinweise
Ein Downcast kann auch mit static_cast durchgeführt werden, was die Kosten der Laufzeitprüfung vermeidet. Dies ist jedoch nur sicher, wenn das Programm (durch eine andere Logik) garantieren kann, dass das Objekt, auf das von Ausdruck gezeigt wird, definitiv Derived ist.
Einige Formen von dynamic_cast basieren auf Run-Time Type Identification (RTTI), d. h. Informationen über jede polymorphe Klasse im kompilierten Programm. Compiler haben typischerweise Optionen, um die Einbeziehung dieser Informationen zu deaktivieren.
[bearbeiten] Schlüsselwörter
[bearbeiten] Beispiel
#include <iostream> struct V { virtual void f() {} // must be polymorphic to use runtime-checked dynamic_cast }; struct A : virtual V {}; struct B : virtual V { B(V* v, A* a) { // casts during construction (see the call in the constructor of D below) dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B* dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of 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; // the most derived object A& a = d; // upcast, dynamic_cast may be used, but unnecessary [[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(); // safe to call } Base* b2 = new Derived; if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr) { std::cout << "downcast from b2 to d successful\n"; d->name(); // safe to call } delete b1; delete b2; }
Ausgabe
downcast from b2 to d successful
[bearbeiten] Defect Reports
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 Ausdruck s durchgeführt, wenn Zieltyp ein rvalue-Referenztyp ist |
durchgeführt |
| CWG 2861 | C++98 | Ausdruck konnte auf ein typ-unzugängliches Objekt zeigen/verweisen | das Verhalten ist in diesem Fall undefiniert |
[bearbeiten] 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]