Aracılığıyla paylaş


dynamic_cast operatörü

İşlenen dönüştürür expression türünde bir nesne için type-id.

dynamic_cast < type-id > ( expression )

Notlar

type-id Bir işaretçi veya önceden tanımlanmış sınıf türü için bir başvuru ya da bir "işaretçi void" olmalıdır. Tür expression bir işaretçi olmalıdır type-id bir işaretçi veya l-değeri type-id yapılan bir başvurudur.

Bkz: static_cast fark statik ve dinamik çevrim dönüşümleri arasında ve her uygun olduğunda bir açıklama için.

Davranışı, iki son değişiklikleri olan dynamic_cast yönetilen kod:

  • dynamic_castbir işaretçi kutu numaralandırma türlerinin dönüştürülmüş işaretçi yerine 0 döndüren zamanında başlayamaz.

  • dynamic_castartık bir özel durum yaratacak, type-id zamanında başarısız cast ile bir değer türü için iç bir işaretçidir. Cast şimdi atma yerine işaretçi 0 değerini döndürür.

type-id Bir belirli erişilebilir doğrudan veya dolaylı temel sınıfı bir işaretçidir expression, bir işaretçi türünde benzersiz subobject type-id sonucudur. Örne?in:

// 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
}

Bu tür bir Dönüşümü "yukarı çevrim" olarak adlandırılır çünkü den türetilen bir sınıfı için türetilmiş sınıftan bir işaretçi bir sınıf hiyerarşisinde yukarı taşır. Bir kapalý dönüþtürme yukarı çevrim olur.

type-id Void * olan bir çalışma zamanı denetimi gerçek türünü belirlemek için yapılan expression. Sonuç olarak sıralanmasını tam nesne bir işaretçidir expression. Örne?in:

// 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
}

type-id Void * değil bir çalışma zamanı denetimi nesne göre sıralanmasını, görmek için yapılan expression göre sıralanmasını türüne dönüştürülebilir type-id.

Türünü expression türü temel sınıftır type-id, bir çalışma zamanı denetimi olmadığını yapılan expression gerçekten tam bir tür nesnesine işaret eden type-id. Değer true ise, tam bir nesne türünü gösteren bir işaretçi sonucu olan type-id. Örne?in:

// 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
}

Bu tür bir dönüşümü adlı bir "downcast" bir işaretçi bir sınıf için verilen bir sınıftan bir sınıf hiyerarşisi aşağı taşır çünkü ondan türetilmiş.

Birden çok devralma durumlarda belirsizlik olasılıklarını kullanılmaya başlanmıştır. Aşağıdaki resimde gösterilen sınıf hiyerarşisi düşünün.

clr türleri için dynamic_cast bir işlem no dönüştürme örtük olarak gerçekleştirilmesi, ya da bir MSIL sonuçlarını isinst dinamik bir denetimi gerçekleştirir ve döner yönerge nullptr dönüştürme başarısız olursa.

Aşağıdaki örnek kullanımlar dynamic_cast bir sınıf belirli türdeki bir örneği olup olmadığını belirlemek için:

// 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);
}

Birden çok devralma gösteren sınıf hiyerarşisi

Birden çok devralma gösteren sınıf hiyerarşisi

Bir işaretçi türünde bir nesne D için güvenli bir şekilde artığını B veya C. Ancak, D işaret edecek şekilde artığını bir A nesne, hangi örneği A neden olur? Bu, belirsiz çevrim hataya neden olur. Bu sorunla karşılaşmamak için iki belirli yayınları gerçekleştirebilirsiniz. Örne?in:

// 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
}

Sanal temel sınıfları kullandığınızda başka ambiguities tanıtılan. Aşağıdaki resimde gösterilen sınıf hiyerarşisi düşünün.

Sınıf hiyerarşisini gösteren sanal temel sınıflar

ClassHierarchyVirtualBaseClasses grafiği

Bu hiyerarşide, A sanal bir taban sınıftır. Bkz: Sanal temel sınıflar sanal bir temel sınıf tanımı. Sınıfının bir örneği verilen E ve bir işaretçi A subobject, bir dynamic_cast için bir işaretçi B belirsizlik nedeniyle başarısız olur. İlk geri tamamlamak için dönüştürmelisiniz E nesne ve hiyerarşi yedekleme doğru ulaşmak için bir belirli şekilde inin B nesne.

Aşağıdaki resimde gösterilen sınıf hiyerarşisi düşünün.

Sınıf hiyerarşisini gösteren yinelenen temel sınıflar

Çoğaltılmış temel sınıfları gösteren sınıf hiyerarşisi

Bir nesne türü verilen E ve bir işaretçi D arasında gezinmek için subobject, D en soldaki subobject A subobject, üç dönüştürme yapılamıyor. Gerçekleştirebileceğiniz bir dynamic_cast dönüştürme D işaretçisine bir E işaretçisi ve sonra bir dönüştürme (ya da dynamic_cast veya bir örtük dönüştürme) dan E için Bve son olarak bir örtük dönüştürme B için A. Örne?in:

// 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 İşleci de kullanılabilir bir "Çapraz cast." gerçekleştirmek için Aynı sınıf hiyerarşisini kullanarak, gelen, örneğin, bir işaretçi artığını mümkündür B için subobject D tam nesne türü olduğu sürece, subobject E.

Yayınları dikkate alındığında, bir işaretçiyi dönüştürme yapmak gerçekten mümkündür D en soldaki bir işaretçi için A subobject iki adımda. Karşı tonunu arası gerçekleştirebilirsiniz D için B, sonra bir örtük dönüştürme B için A. Örne?in:

// 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
}

Bir null işaretçi değeri hedef türüne göre işaretçi null değerine dönüştürülür dynamic_cast.

Kullandığınızda dynamic_cast < type-id > ( expression ), expression yazmak için güvenli bir şekilde dönüştürülemez type-id, çalışma zamanı denetimi cast başarısız olmasına neden olur. Örne?in:

// 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
}

Başarısız bir cast işaretçi türü null işaretçi değerdir. Tür throws başvurmak için başarısız bir cast bir bad_cast özel durum.   expression Olmayan işaret veya geçerli bir nesne başvurusu bir __non_rtti_object exception Is thrown.

Bkz: TypeID açıklaması için __non_rtti_object özel durum.

Örnek

Aşağıdaki örnek temel sınıf (struct a) işaretçisine bir nesne (struct c) oluşturur. Bu artı gerçeği orada sanal İşlevler, çalışma zamanı çok biçimlilik sağlar.

Örnek, aynı zamanda hiyerarşisinde bir sanal olmayan işlevini çağırır.

// 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);
}
  

Ayrıca bkz.

Başvuru

Atama operatörleri

C++ anahtar sözcükler