Operator dynamic_cast
Konvertiert den Operanden expression in ein Objekt des Typs type-id.
dynamic_cast < type-id > ( expression )
Hinweise
type-id muss ein Zeiger oder einen Verweis zu einem zuvor definierten Klassentyps aufzuheben oder ein „Zeiger“ sein.Der Typ der expression muss ein Zeiger, wenn type-id ein Zeiger ist oder ein L-Wert sein, wenn type-id ein Verweis ist.
Weitere Informationen finden Sie unter static_cast für eine Erklärung des Unterschied zwischen den statischen und dynamischen Umwandlungs konvertierungen und wenn sie jeweils geeignet ist.
Es gibt zwei wichtige Änderungen im Verhalten von dynamic_cast in verwaltetem Code:
dynamic_cast auf einen Zeiger auf den zugrunde liegenden Typ einer geschachtelten Enumeration schlägt zur Laufzeit fehl und gibt 0 anstelle des konvertierten Zeigers zurück.
dynamic_cast nicht mehr löst eine Ausnahme aus, wenn type-id ein innerer Zeiger auf einen Werttyp ist, wenn die Umwandlung zur Laufzeit fehlschlägt.Die Umwandlung gibt jetzt den 0 Zeigerwert zurück, statt auszulösen.
Wenn type-id ein Zeiger auf eine eindeutigen zugreifbaren direkten oder indirekten Basisklasse expressionist, ist ein Zeiger auf den eindeutigen Unterobjekt vom Typ type-id das Ergebnis.Beispiele:
// dynamic_cast_1.cpp
// compile with: /c
class B { };
class C : public B { };
class D : public C { };
void f(D* pd) {
C* pc = dynamic_cast<C*>(pd); // ok: C is a direct base class
// pc points to C subobject of pd
B* pb = dynamic_cast<B*>(pd); // ok: B is an indirect base class
// pb points to B subobject of pd
}
Diese Art der Konvertierung wird eine Aufwärtsumwandlung“, da er einen Zeiger eine Klassenhierarchie verschiebt, einer abgeleiteten Klasse auf eine Klasse aufgerufen, in der sie abgeleitet ist.Eine Aufwärtsumwandlung ist eine implizite Konvertierung.
Wenn type-id void* ist, wird eine Laufzeitüberprüfung durchgeführt, um den tatsächlichen Typ der expressionzu bestimmen.Das Ergebnis ist ein Zeiger auf das gesamte Objekt, das durch expressiondargestellt wird.Beispiele:
// dynamic_cast_2.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = new B;
void* pv = dynamic_cast<void*>(pa);
// pv now points to an object of type A
pv = dynamic_cast<void*>(pb);
// pv now points to an object of type B
}
Wenn keine type-id void* ist, wird eine Laufzeitüberprüfung durchgeführt, um festzustellen, ob das Objekt, auf das durch expression dargestellt wird, in einen Typ konvertiert werden kann, der durch type-iddargestellt wird.
Wenn der Typ von expression eine Basisklasse Typ der type-idist, wird eine Laufzeitüberprüfung durchgeführt, um festzustellen, ob expression sich tatsächlich zu einem vollständigen Objekt des Typs von type-idwird.Wenn dies der Fall ist, ist das Ergebnis ein Zeiger auf einen vollständigen Objekt des Typs von type-id.Beispiele:
// dynamic_cast_3.cpp
// compile with: /c /GR
class B {virtual void f();};
class D : public B {virtual void f();};
void f() {
B* pb = new D; // unclear but ok
B* pb2 = new B;
D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D
D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D
}
Diese Art der Konvertierung wird eine „Umwandlung“, da er einen Zeiger einer Klassenhierarchie nach unten verschoben, von einer bestimmten Klasse zu einer Klasse aufgerufen, die davon abgeleitet ist.
Im Fall der Mehrfachvererbung werden Möglichkeiten für Mehrdeutigkeit eingeführt.Betrachten Sie die Klassenhierarchie, die in der folgenden Abbildung gezeigt wird.
Für CLR-Typen ergibt dynamic_cast jedes einen No-Op implizit, wenn die Konvertierung durchgeführt werden kann, oder eine Anweisung, die eine isinst MSIL Betriebsprüfung ausführt und nullptr zurückgibt, wenn die Konvertierung fehlschlägt.
Im folgenden Beispiel wird dynamic_cast , um zu bestimmen, ob eine Klasse eine Instanz des angegebenen Typs ist:
// dynamic_cast_clr.cpp
// compile with: /clr
using namespace System;
void PrintObjectType( Object^o ) {
if( dynamic_cast<String^>(o) )
Console::WriteLine("Object is a String");
else if( dynamic_cast<int^>(o) )
Console::WriteLine("Object is an int");
}
int main() {
Object^o1 = "hello";
Object^o2 = 10;
PrintObjectType(o1);
PrintObjectType(o2);
}
Klassenhierarchie-Vertretungs-Mehrfachvererbung
Ein Zeiger auf ein Objekt des Typs D kann auf B oder sicher Cumgewandelt werden.Wenn jedoch D umgewandelt wird, um zu einem A-Objekt verweisen, das Instanz von A resultieren würde?Dies würde einen mehrdeutigen Umwandlungs von Fehlern führen.Um dieses Problem zu erhalten, können Sie zwei eindeutige Typumwandlungen ausführen.Beispiele:
// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
class D : public B {virtual void f();};
void f() {
D* pd = new D;
B* pb = dynamic_cast<B*>(pd); // first cast to B
A* pa2 = dynamic_cast<A*>(pb); // ok: unambiguous
}
Alle anderen Mehrdeutigkeiten können eingegeben werden, wenn Sie virtuelle Basisklasse verwenden.Betrachten Sie die Klassenhierarchie, die in der folgenden Abbildung gezeigt wird.
Klassenhierarchie-Vertretungs-virtuelle Basisklassen
In dieser Hierarchie ist A eine virtuelle Basisklasse.Weitere Informationen finden Sie unter Virtuelle Basisklassen für die Definition einer virtuellen Basisklasse.Dargestellt wird es liegt eine Instanz der Klasse E und eines Zeigers auf den A Unterobjekt, dynamic_cast in einen Zeiger auf B aufgrund der Mehrdeutigkeit aus.Sie müssen auf vollständige E das Objekt zunächst umwandeln, funktionieren die Methoden in der Hierarchie sicherung eine eindeutige Weise, das richtige B-Objekt zu erhalten.
Betrachten Sie die Klassenhierarchie, die in der folgenden Abbildung gezeigt wird.
Klassenhierarchie-Vertretungs-Duplikats-Basisklassen
Dargestellt wird es kann ein Objekt des Typs E und eines Zeigers auf den D Unterobjekt vom D Unterobjekt auf das sich am weitesten links befindende A Unterobjekt zu navigieren, drei Konvertierungen vorgenommen wurden.Sie können eine dynamic_cast Konvertierung vom D Zeiger auf einen Zeiger E ausführen, eine Konvertierung (entweder dynamic_cast oder eine implizite Konvertierung) von E zu Bund schließlich eine implizite Konvertierung von B zu A.Beispiele:
// dynamic_cast_5.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
void f(D* pd) {
E* pe = dynamic_cast<E*>(pd);
B* pb = pe; // upcast, implicit conversion
A* pa = pb; // upcast, implicit conversion
}
Der dynamic_cast-Operator kann auch verwendet werden, um eine „- Cross-Compiler umwandlung“ auszuführen. Verwenden der gleichen Klassenhierarchie ist es möglich, einen Zeiger auf den vom B Unterobjekt B. dem D Unterobjekt umzuwandeln, solange das gesamte Objekt vom Typ Eist.
umwandlungen - Cross-Compiler betrachtend, ist es möglich, die tatsächlich Konvertierung von einem Zeiger auf D auf einen Zeiger auf den am weitesten links stehende A Unterobjekt in nur zwei Schritten durchführen.Sie können ein - Cross-Compiler, das von D zu B, eine implizite Konvertierung ausführen aus B zu Aumgewandelt wird.Beispiele:
// dynamic_cast_6.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
void f(D* pd) {
B* pb = dynamic_cast<B*>(pd); // cross cast
A* pa = pb; // upcast, implicit conversion
}
Ein NULL-Zeiger-Wert wird dem NULL-Zeiger-Wert des Zieltyps von dynamic_castkonvertiert.
Wenn Sie dynamic_cast < type-id > ( expression )verwenden, wenn expression nicht sicher konvertiert werden kann, um einzugeben type-idführt die Laufzeitüberprüfung die Umwandlung fehlschlägt.Beispiele:
// dynamic_cast_7.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = dynamic_cast<B*>(pa); // fails at runtime, not safe;
// B not derived from A
}
Der Wert einer fehlgeschlagenen Umwandlung in den Zeigertyp ist der NULL-Zeiger.Eine Umwandlung in den Referenztyp bad_cast Ausnahmelöst Fehler aus. Wenn expression oder wird nicht auf ein gültiges Objekt verweist, wird eine __non_rtti_object Ausnahme ausgelöst.
Weitere Informationen finden Sie unter typeid zur Erläuterung der Ausnahme __non_rtti_object .
Beispiel
Im folgenden Beispiel wird die Struktur der Zeiger Basisklasse (A) zu einem Objekt C (Struktur).Dieses sowie die Tatsache virtuelle Funktionen vorhanden sind, können die polymorphie.
Im Beispiel wird außerdem eine nicht virtuelle Funktion in der Hierarchie an.
// dynamic_cast_8.cpp
// compile with: /GR /EHsc
#include <stdio.h>
#include <iostream>
struct A {
virtual void test() {
printf_s("in A\n");
}
};
struct B : A {
virtual void test() {
printf_s("in B\n");
}
void test2() {
printf_s("test2 in B\n");
}
};
struct C : B {
virtual void test() {
printf_s("in C\n");
}
void test2() {
printf_s("test2 in C\n");
}
};
void Globaltest(A& a) {
try {
C &c = dynamic_cast<C&>(a);
printf_s("in GlobalTest\n");
}
catch(std::bad_cast) {
printf_s("Can't cast to C\n");
}
}
int main() {
A *pa = new C;
A *pa2 = new B;
pa->test();
B * pb = dynamic_cast<B *>(pa);
if (pb)
pb->test2();
C * pc = dynamic_cast<C *>(pa2);
if (pc)
pc->test2();
C ConStack;
Globaltest(ConStack);
// will fail because B knows nothing about C
B BonStack;
Globaltest(BonStack);
}