dynamic_cast 演算子dynamic_cast Operator

オペランド expressiontype-id 型のオブジェクトに変換します。Converts the operand expression to an object of type type-id.

構文Syntax

dynamic_cast < type-id > ( expression )

RemarksRemarks

type-id は、以前に定義されたクラス型への参照またはポインター、または "void 型へのポインター" である必要があります。The type-id must be a pointer or a reference to a previously defined class type or a "pointer to void". expression の型は、type-id がポインターの場合はポインター、type-id が参照の場合は左辺値である必要があります。The type of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.

参照してくださいstatic_cast各を使用する適切なタイミングと、静的および動的なキャスト変換の間の違いの詳細についてはします。See static_cast for an explanation of the difference between static and dynamic casting conversions, and when it is appropriate to use each.

動作の 2 つの重大な変更があるdynamic_castマネージ コードで。There are two breaking changes in the behavior of dynamic_cast in managed code:

  • dynamic_castボックス化された列挙型の基になる型へのポインターに変換されたポインターではなく 0 を返す、実行時に失敗します。dynamic_cast to a pointer to the underlying type of a boxed enum will fail at runtime, returning 0 instead of the converted pointer.

  • dynamic_castは例外をスローしないときtype-idは実行時に失敗したキャストの値の型への内部ポインター。dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. キャストは、スローする代わりに、ポインター値 0 を返します。The cast will now return the 0 pointer value instead of throwing.

type-idexpression の明確でアクセス可能な直接または間接的な基底クラスへのポインターである場合、結果は type-id 型の一意のサブオブジェクトへのポインターになります。If type-id is a pointer to an unambiguous accessible direct or indirect base class of expression, a pointer to the unique subobject of type type-id is the result. 例えば:For example:

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

このような変換は "アップキャスト" と呼ばれます。理由は、クラスの階層構造で、派生したクラスから上位に (つまり、そのクラスの派生元のクラスに) ポインターを移動するためです。This type of conversion is called an "upcast" because it moves a pointer up a class hierarchy, from a derived class to a class it is derived from. アップキャストは暗黙の変換です。An upcast is an implicit conversion.

type-id が void* の場合、expression の実際の型を確認するためにランタイム チェックが行われます。If type-id is void*, a run-time check is made to determine the actual type of expression. 結果は expression によってポイントされた完全なオブジェクトへのポインターです。The result is a pointer to the complete object pointed to by expression. 例:For example:

// 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* でない場合は、expression によって指し示されるオブジェクトが type-id 型によって指し示される型に変換できるかどうかを確認するランタイム チェックが行われます。If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted to the type pointed to by type-id.

expression の型が type-id の型の基底クラスである場合は、ランタイム チェックが実行されて、expressiontype-id の型の完全なオブジェクトを実際に指し示しているかどうかが確認されます。If the type of expression is a base class of the type of type-id, a run-time check is made to see if expression actually points to a complete object of the type of type-id. 実際に指し示している場合、結果は type-id の型の完全なオブジェクトへのポインターになります。If this is true, the result is a pointer to a complete object of the type of type-id. 例えば:For example:

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

このような変換は "ダウンキャスト" と呼ばれます。理由は、クラスの階層構造で特定のクラスから下位に (つまり、そのクラスから派生したクラスに) ポインターを移動するためです。This type of conversion is called a "downcast" because it moves a pointer down a class hierarchy, from a given class to a class derived from it.

多重継承の場合、あいまいさが生じる可能性があります。In cases of multiple inheritance, possibilities for ambiguity are introduced. 次の図に示すクラスの階層構造の場合を考えてみましょう。Consider the class hierarchy shown in the following figure.

CLR 型dynamic_cast no-op、変換を暗黙的に実行できない場合または MSIL のいずれかで結果isinst命令では、動的チェックを実行し、返しますnullptr場合、変換は失敗します。For CLR types, dynamic_cast results in either a no-op if the conversion can be performed implicitly, or an MSIL isinst instruction, which performs a dynamic check and returns nullptr if the conversion fails.

次のサンプルはdynamic_castクラスが特定の種類のインスタンスかどうかを決定します。The following sample uses dynamic_cast to determine if a class is an instance of particular type:

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

クラスを示す複数継承階層Class hierarchy that shows multiple inheritance
複数の継承を示すクラスの階層構造Class hierarchy that shows multiple inheritance

D 型のオブジェクトへのポインターは、B または C に安全にキャストできます。A pointer to an object of type D can be safely cast to B or C. しかし、DA オブジェクトを指し示すようにキャストされる場合、結果は A のどのインスタンスになるでしょうか。However, if D is cast to point to an A object, which instance of A would result? このような場合に、あいまいなキャスト エラーが発生します。This would result in an ambiguous casting error. この問題を回避するには、2 種類の明確なキャストを実行します。To get around this problem, you can perform two unambiguous casts. 例えば:For example:

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

仮想基底クラスを使用するときに、あいまいさが発生する可能性もあります。Further ambiguities can be introduced when you use virtual base classes. 次の図に示すクラスの階層構造の場合を考えてみましょう。Consider the class hierarchy shown in the following figure.

クラスの仮想基底クラスを示す階層Class hierarchy that shows virtual base classes
仮想基底クラスを示すクラスの階層構造Class hierarchy that shows virtual base classes

この階層構造では、A は仮想基底クラスです。In this hierarchy, A is a virtual base class. クラスのインスタンスを指定されたEへのポインター、Aサブオブジェクトをdynamic_castへのポインターにBあいまいさが原因で失敗します。Given an instance of class E and a pointer to the A subobject, a dynamic_cast to a pointer to B will fail due to ambiguity. 最初に、完全な E オブジェクトにキャストし、その後、明確な方法で階層を上へとたどり、正しい B オブジェクトに到達する必要があります。You must first cast back to the complete E object, then work your way back up the hierarchy, in an unambiguous manner, to reach the correct B object.

次の図に示すクラスの階層構造の場合を考えてみましょう。Consider the class hierarchy shown in the following figure.

クラスの基底クラスの複製を示す階層Class hierarchy that shows duplicate base classes
重複基底クラスを示すクラスの階層構造Class hierarchy that shows duplicate base classes

E 型のオブジェクトと D サブオブジェクトへのポインターがあるとして、D サブオブジェクトから左端の A サブオブジェクトに移動するには、変換を 3 回行います。Given an object of type E and a pointer to the D subobject, to navigate from the D subobject to the left-most A subobject, three conversions can be made. 行うことができます、 dynamic_castからの変換、Dへのポインター、Eポインターの場合、変換 (かdynamic_castまたは暗黙の変換)からEB、および暗黙的な変換から最後にBAします。You can perform a dynamic_cast conversion from the D pointer to an E pointer, then a conversion (either dynamic_cast or an implicit conversion) from E to B, and finally an implicit conversion from B to A. 例:For example:

// 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演算子が「クロス キャスト」を実行することもできますThe dynamic_cast operator can also be used to perform a "cross cast." 同じクラス階層を使用すると、完全なオブジェクトが B 型であれば、たとえば D サブオブジェクトから E サブオブジェクトへのように、ポインターをキャストできます。Using the same class hierarchy, it is possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object is of type E.

クロス キャストを考慮すると、D へのポインターから左端の A サブオブジェクトへのポインターへの変換は、実際には 2 ステップで行うことができます。Considering cross casts, it is actually possible to do the conversion from a pointer to D to a pointer to the left-most A subobject in just two steps. D から B にクロス キャストを実行してから、B から A への暗黙の型変換を実行できます。You can perform a cross cast from D to B, then an implicit conversion from B to A. 例えば:For example:

// 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 ポインター値は、変換先の型の null ポインター値に変換されますdynamic_castします。A null pointer value is converted to the null pointer value of the destination type by dynamic_cast.

dynamic_cast < type-id > ( expression ) を使用するときに、expression を型 type-id に安全に変換できない場合、ランタイム チェックにより、キャストは失敗します。When you use dynamic_cast < type-id > ( expression ), if expression cannot be safely converted to type type-id, the run-time check causes the cast to fail. 例:For example:

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

ポインター型への失敗したキャストの値は、null ポインターです。The value of a failed cast to pointer type is the null pointer. 失敗したキャスト型のスローを参照する、 bad_cast 例外します。A failed cast to reference type throws a bad_cast Exception. 場合expression をポイントまたは有効なオブジェクトを参照しません、__non_rtti_object例外がスローされます。If expression does not point to or reference a valid object, a __non_rtti_object exception is thrown.

参照してくださいtypeidの詳細については、__non_rtti_object例外。See typeid for an explanation of the __non_rtti_object exception.

Example

次のサンプルは、オブジェクト (構造体 C) への基底クラス (構造体 A) ポインターを作成します。The following sample creates the base class (struct A) pointer, to an object (struct C). このことと、仮想関数があるという事実によって、実行時ポリモーフィズムが可能になります。This, plus the fact there are virtual functions, enables runtime polymorphism.

このサンプルでは、階層内の非仮想関数も呼び出します。The sample also calls a non-virtual function in the hierarchy.

// 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);
}
in C
test2 in B
in GlobalTest
Can't cast to C

関連項目See also

キャスト演算子Casting Operators
キーワードKeywords