Namensräume
Varianten
Aktionen

dynamic_cast-Konvertierung

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

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.

1) Wenn der Typ von Ausdruck exakt Zieltyp oder eine weniger cv-qualifizierte Version von Zieltyp ist, ist das Ergebnis der Wert von Ausdruck mit dem Typ Zieltyp. Mit anderen Worten, dynamic_cast kann verwendet werden, um constness hinzuzufügen. Eine implizite Konvertierung und static_cast können diese Konvertierung ebenfalls durchführen.
2) Wenn Zieltyp „Zeiger auf (möglicherweise cv-qualifiziertes) 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 Base Unterobjekt des Derived-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.
3) Wenn Zieltyp „Referenz auf (möglicherweise cv-qualifiziertes) 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.
4) Wenn Ausdruck ein Nullzeigerwert eines polymorphen Typs ist, ist das Ergebnis der Nullzeigerwert von Zieltyp.
4) Andernfalls muss Ausdruck ein Zeiger oder eine Referenz auf ein Objekt eines polymorphen Typs sein, das sich innerhalb seiner Lebensdauer oder innerhalb seiner Konstruktions- oder Zerstörungsperiode befindet und dessen Typ mit dem Typ von Ausdruck ähnlich ist (andernfalls ist das Verhalten undefiniert).
a) Wenn Ausdruck ein Zeiger auf (möglicherweise cv-qualifiziertes) void ist, ist das Ergebnis ein Zeiger auf das am weitesten abgeleitete Objekt, auf das von Ausdruck gezeigt wird.
b) Andernfalls wird eine Laufzeitprüfung durchgeführt, um festzustellen, ob das Objekt, auf das von Ausdruck gezeigt oder verwiesen wird, in den Typ Target konvertiert werden kann, auf den Zieltyp zeigt oder verweist.
i) Wenn in dem am weitesten abgeleiteten Objekt, auf das von Ausdruck gezeigt oder verwiesen wird, Ausdruck auf ein öffentliches Basisklassen-Unterobjekt eines 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).
ii) Andernfalls, wenn Ausdruck auf ein öffentliches Basisklassen-Unterobjekt des am weitesten abgeleiteten Objekts zeigt/verweist und der Typ des am weitesten abgeleiteten Objekts eine eindeutige und öffentliche Basisklasse vom Typ 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.
iii) Andernfalls schlägt die Laufzeitprüfung fehl.
  • 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

  • ein lvalue, wenn Zieltyp ein Referenztyp ist.
  • ein rvalue, wenn Zieltyp ein Zeigertyp ist.
(bis C++11)
  • ein lvalue, wenn Zieltyp ein lvalue-Referenztyp ist (Ausdruck muss ein lvalue sein).
  • ein xvalue, wenn Zieltyp ein rvalue-Referenztyp ist (Ausdruck kann lvalue oder rvalue sein(bis C++17)muss ein glvalue sein (prvalues werden materialisiert)(seit C++17) eines vollständigen Klassentyps).
  • ein prvalue, wenn Zieltyp ein Zeigertyp ist.
(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

dynamic_cast

[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]

[bearbeiten] Siehe auch