Aracılığıyla paylaş


dynamic_cast İşleci

İşleneni expression türünde type-idbir nesneye dönüştürür.

Sözdizimi

dynamic_cast < type-id > ( expression )

Açıklamalar

, type-id önceden tanımlanmış bir sınıf türüne veya "void işaretçisine" bir işaretçi veya başvuru olmalıdır. türü expression işaretçi ise type-id işaretçi veya başvuru ise type-id l değeri olmalıdır.

Statik ve dinamik atama dönüştürmeleri arasındaki farkın ve bunların ne zaman kullanılmasının uygun olduğunu gösteren bir açıklama için bkz . static_cast .

Yönetilen kodda davranışında iki hataya neden olan dynamic_cast değişiklik vardır:

  • dynamic_cast kutulanmış bir sabit kutusunun temel türüne ilişkin bir işaretçi çalışma zamanında başarısız olur ve dönüştürülen işaretçi yerine 0 döndürür.

  • dynamic_cast artık bir değer türünün iç işaretçisi olduğunda type-id özel durum oluşturmaz; bunun yerine atama çalışma zamanında başarısız olur. Atama, atmak yerine 0 işaretçisi değerini döndürür.

açık olmayan erişilebilir doğrudan veya dolaylı temel sınıfına expressionyönelik bir işaretçiysetype-id, türün type-id benzersiz alt nesnesine yönelik bir işaretçi sonuç olur. Örnek:

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

Bir işaretçiyi türetilmiş bir sınıftan türetildiği sınıfa bir sınıf hiyerarşisi yukarı taşıması nedeniyle bu dönüştürme türüne "yukarı yayın" adı verilir. Yukarı yayın örtük bir dönüştürmedir.

geçersizse type-id *, gerçek türünü expressionbelirlemek için bir çalışma zamanı denetimi yapılır. Sonuç, tarafından expressionişaret edilen tam nesnenin işaretçisidir. Örnek:

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

değilse type-idvoid*, tarafından işaret edilen nesnenin tarafından işaret edilen türe dönüştürülip dönüştürülemediğini görmek için expressiontype-idbir çalışma zamanı denetimi yapılır.

türü expression türünün temel sınıfıysatype-id, türünün tam bir nesnesine type-idişaret olup olmadığını expression görmek için bir çalışma zamanı denetimi yapılır. Bu doğruysa, sonuç türündeki tam bir nesnenin işaretçisidir type-id. Örnek:

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

Bir işaretçiyi bir sınıf hiyerarşisinin aşağısına, belirli bir sınıftan türetilen bir sınıfa taşıması nedeniyle bu tür dönüştürmeye "aşağı yayın" adı verilir.

Birden çok devralma durumunda belirsizlik olasılıkları ortaya çıkmıştır. Aşağıdaki şekilde gösterilen sınıf hiyerarşisini göz önünde bulundurun.

CLR türleri için, dynamic_cast dönüştürme örtük olarak gerçekleştirilebiliyorsa işlem yapılmaz veya dinamik denetim gerçekleştiren ve dönüştürme başarısız olursa döndüren nullptr bir MSIL isinst yönergesi elde eder.

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

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

Diagram that shows multiple inheritance.

Diyagramda, temel bir D sınıfı olan B'nin temel sınıfı olarak A ile bir sınıf hiyerarşisi gösterilir. A aynı zamanda C için bir temel sınıftır ve bu da D için bir temel sınıftır. D Sınıfı hem B hem de C'den devralır.

Türünde D bir nesnenin işaretçisi veya Cöğesine B güvenli bir şekilde atanabilir. Ancak, bir A nesneye işaret edecek şekilde yayınlanırsaD, hangi örneği A sonuçlanır? Bu, belirsiz bir atama hatasına neden olur. Bu sorunu çözmek için iki kesin atama gerçekleştirebilirsiniz. Örnek:

// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A {virtual void f();};
class D : public B, public C {virtual void f();};

void f() {
   D* pd = new D;
   A* pa = dynamic_cast<A*>(pd);   // C4540, ambiguous cast fails at runtime
   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 daha fazla belirsizlik ortaya eklenebilir. Aşağıdaki şekilde gösterilen sınıf hiyerarşisini göz önünde bulundurun.

Diagram of a class hierarchy that shows virtual base classes.

Diyagramda A, B, C, D ve E sınıfları şu şekilde düzenlenmiştir: Sınıf A, B'nin temel sınıfıdır. C ve E sınıflarının her biri B'den türetilir. E Sınıfı da A sınıfından devralan B sınıfından devralan D sınıfından devralır.

Sanal temel sınıfları gösteren sınıf hiyerarşisi

Bu hiyerarşide bir A sanal temel sınıftır. Sınıfın E bir örneği ve alt nesneye A yönelik bir işaretçi verilip belirsizlik dynamic_cast nedeniyle başarısız olması için B bir işaretçi. Doğru nesneye ulaşmak için önce tam E nesneye geri döndürmeniz, ardından hiyerarşiyi kesin olmayan bir şekilde yedeklemeniz B gerekir.

Aşağıdaki şekilde gösterilen sınıf hiyerarşisini göz önünde bulundurun.

Diagram of a class hierarchy that shows duplicate base classes.

Diyagramda A, B, C, D ve E sınıfları şu şekilde düzenlenmiş şekilde gösterilir: B Sınıfı A Sınıfından türetilir. C Sınıfı A sınıfından türetilir. D sınıfı B sınıfından türetilir. E Sınıfı, A sınıfından türetilen C sınıfından türetilir. Bu durumda, yinelenen temel sınıf, doğrudan veya dolaylı olarak diğer tüm sınıflar tarafından devralınan A sınıfıdır. A sınıfı doğrudan B ve C sınıfları tarafından, dolaylı olarak B sınıfı aracılığıyla D sınıfı tarafından ve C sınıfı aracılığıyla dolaylı olarak E sınıfı tarafından ve B sınıfı aracılığıyla dolaylı olarak D sınıfı tarafından devralınır.

Yinelenen temel sınıfları gösteren sınıf hiyerarşisi

Türünde E bir nesne ve alt nesne işaretçisi D verilip alt nesneden D en soldaki A alt nesneye gitmek için üç dönüştürme yapılabilir. İşaretçiden bir dynamic_castE işaretçiye dönüştürme, sonra 'dan EBD öğesine dönüştürme (dynamic_castveya örtük dönüştürme) ve son olarak 'dan B 'a Aörtük dönüştürme gerçekleştirebilirsiniz. Örnek:

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

işleci dynamic_cast bir "çapraz atama" gerçekleştirmek için de kullanılabilir. Aynı sınıf hiyerarşisini kullanarak, tam nesne türünde Eolduğu sürece, örneğin, alt nesneden B alt nesneye D bir işaretçi oluşturmak mümkündür.

Çapraz atamaları göz önünde bulundurarak, bir işaretçiden D en soldaki A alt nesneye doğru bir işaretçiye dönüştürmeyi yalnızca iki adımda yapmak mümkündür. 'den D öğesine Bçapraz atama ve ardından 'den BAöğesine örtük dönüştürme gerçekleştirebilirsiniz. Örnek:

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

Null işaretçi değeri, tarafından dynamic_casthedef türün null işaretçi değerine dönüştürülür.

kullandığınızda dynamic_cast < type-id > ( expression ), expression türüne type-idgüvenli bir şekilde dönüştürülemiyorsa, çalışma zamanı denetimi atamanın başarısız olmasına neden olur. Örnek:

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

İşaretçi türüne atanamayan bir değeri null işaretçidir. Başvuru türüne başarısız olan bir atama, bad_cast Özel Durumu oluşturur. Geçerli bir nesneye işaret etmiyor veya bu nesneye başvurmuyorsa expression , bir __non_rtti_object özel durum oluşturulur.

Özel durumun açıklaması için bkz. typeid.__non_rtti_object

Örnek

Aşağıdaki örnek, bir nesne (yapı C) için temel sınıf (yapı A) işaretçisini oluşturur. Bunun yanı sıra sanal işlevler olduğu gerçeği, çalışma zamanı polimorfizmini etkinleştirir.

Örnek, hiyerarşideki sanal olmayan bir işlevi de ç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);

   // fails because B knows nothing about C
    B BonStack;
    Globaltest(BonStack);
}
in C
test2 in B
in GlobalTest
Can't cast to C

Ayrıca bkz.

Atama İşleçleri
Anahtar Sözcükler