Sdílet prostřednictvím


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

Hierarchie třídy znázorňující vícenásobnou dědičnost

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

ClassHierarchyVirtualBaseClasses – grafika

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

Hierarchie třídy znázorňují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);
}
  

Viz také

Referenční dokumentace

Obsazení operátory

Klíčových slov jazyka C++