dynamic_cast operátora
Převede operand expression na objekt typu type-id.
dynamic_cast < type-id > ( expression )
Poznámky
type-id Musí být ukazatel nebo odkaz na typ dříve definované třídy nebo "ukazatel na void".Typ expression musí být ukazatel, pokud type-id je ukazatel nebo l hodnota, pokud type-id je odkaz.
Viz static_cast vysvětlení rozdílu mezi statické a dynamické obsazení převody a je vhodné použít každý.
Existují dvě dodatečné změny v chování dynamic_cast ve spravovaném kódu:
dynamic_castukazatel na základní typ krabici enum nezdaří běhu vrácení 0 namísto převedené ukazatel.
dynamic_castjiž vyvolají výjimku při type-id je vnitřní ukazatel na hodnotu typu, s cast selhání při běhu.Tavby nyní vrátí hodnotu 0 ukazatel namísto vyvolání.
Pokud type-id je ukazatel na jednoznačné přístupné přímé nebo nepřímé základní třídu z expression, ukazatel na jedinečný určitých podřízených objektů typu type-id je výsledek.Příklad:
// 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
}
Tento typ převodu se nazývá "povýšení", protože přesune ukazatel myši nahoru hierarchie třídy, ze třídy odvozené třídy, který je odvozen od.Povýšení je implicitní převod.
Pokud type-id je void * spuštění ověření určit skutečný typ expression.Výsledkem je ukazatel na celý objekt odkazuje expression.Příklad:
// 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
}
Pokud type-id není void * spuštění ověření zobrazíte, pokud objekt odkazuje expression lze převést na typ odkazuje type-id.
Pokud typ expression je základní třídy typu type-id, zda je provedena kontrola spuštění expression ve skutečnosti odkazuje na celý objekt typu type-id.Pokud je true, výsledkem je ukazatel na celý objekt typu type-id.Příklad:
// 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
}
Tento typ převodu se nazývá "downcast", protože ji přesune ukazatel dolů hierarchii třídy z dané třídy do třídy odvozené od něj.
V případě více dědičnosti jsou zavedeny možnosti nejednoznačnosti.Zvažte hierarchie třídy ukazuje následující obrázek.
CLR typů dynamic_cast vede k operaci-li převod lze provést implicitně nebo MSIL isinst instrukce, která provede dynamickou kontrolu a vrátí nullptr Pokud se převod nezdařil.
Následující ukázka použití dynamic_cast zjistit třídu je instance určitého typu:
// 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);
}
Vícenásobné dědění znázorňující hierarchie třídy
Ukazatel na objekt typu D lze bezpečně přetypovat na B nebo C.Však pokud D je nádech přejděte A objektu, která instance A by?Výsledkem by bylo při obsazení dvojznačný.Chcete-li tento problém vyřešit, můžete provést dvě jednoznačné nádech.Příklad:
// 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
}
Další nejasnosti lze zavést pomocí virtuální základní třídy.Zvažte hierarchie třídy ukazuje následující obrázek.
Virtuální základní třídy zobrazení hierarchie třídy
V této hierarchii A je virtuální základní třídy.Viz Virtuální základní třídy pro definici virtuální základní třídy.Dané instanci třídy E a ukazatel na A určitých podřízených objektů, dynamic_cast na ukazatel na B kvůli nejednoznačnosti nezdaří.Musíte nejprve odevzdaných zpět na úplnou E objektu, pak fungují vaše zálohovat v hierarchii jednoznačným způsobem dosáhnout správné B objektu.
Zvažte hierarchie třídy ukazuje následující obrázek.
Třída hierarchie zobrazující duplicitní základní třídy
Objekt typu dané E a ukazatel na D přejít z určitých podřízených objektů D určitých podřízených objektů na nejvíce vlevo A subobject lze použít tři převody.Můžete provést dynamic_cast převodu z D ukazatele E ukazatel, pak převod (buď dynamic_cast nebo implicitní převod) z E na Ba nakonec je implicitní převod z B na A.Příklad:
// 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
}
dynamic_cast Operátor lze také provést "křížové cast". Pomocí stejné hierarchie třídy je možné přetypovat ukazatel, například z B k subobject D subobject, jako je celý objekt typu E.
Posuzování přeshraničních nádech, je skutečně možné provést převod z ukazatele na D na ukazatel pro nejvíce vlevo A určitých podřízených objektů pouze dva kroky.Můžete provést křížové nádech z D na B, pak je implicitní převod z B na A.Příklad:
// 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
}
Ukazatele null hodnota je převedena na hodnotu ukazatele null typu určení podle dynamic_cast.
Při použití dynamic_cast < type-id > ( expression ), pokud expression nelze bezpečně převést na typ type-id, způsobí spuštění kontrola osazení selhání.Příklad:
// 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
}
Selhání cast typu ukazatel hodnotu ukazatele null.Neúspěšné cast vyvolá typ odkazu bad_cast výjimku. Pokud expression příkaz nebo odkazovat na platný objekt __non_rtti_object je výjimka.
Viz typeid vysvětlení __non_rtti_object výjimku.
Příklad
Následující příklad vytvoří základní třídy (struktura A) ukazatel myši na objekt (struct C).To plus skutečnost virtuální funkce, umožňuje runtime, polymorfismus.
Vzorek také volání-virtuální funkce v hierarchii.
// 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);
}