名前空間
変種
操作

dynamic_cast 変換

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (非推奨)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

継承階層に沿って上へ、下へ、および横へ、クラスへのポインタおよび参照を安全に変換します。

目次

[編集] 構文

dynamic_cast < new_type > ( expression )
new_type - 完全クラス型へのポインタ、完全クラス型への参照、または void (cv 修飾されていても構いません) へのポインタ。
expression - new_type が参照の場合は完全クラス型の lvalue (C++11以前)glvalue (C++11およびそれ以降)new_type がポインタの場合は完全クラス型へのポインタの prvalue。

キャストが成功した場合、 dynamic_castnew_type 型の値を返します。 キャストが失敗し、 new_type がポインタ型の場合は、その型のヌルポインタを返します。 キャストが失敗し、 new_type が参照型の場合は、 std::bad_cast 型のハンドラにマッチする例外を投げます。

[編集] 説明

以下の変換のみが dynamic_cast を用いて行うことができます。 ただし cv 修飾を除去することはできません。

1) expression の型が new_type と正確に同じであるか、 new_type の cv 修飾がより少ないバージョンである場合、結果は new_type の型を持つ expression の値です (別の言い方をすると、 dynamic_cast は cv 修飾を追加することができます。 暗黙の変換および static_cast も同様にこの変換を行うことができます)。
2) expression の値がヌルポインタ値の場合、結果は new_type 型のヌルポインタ値です。
3) new_typeBase へのポインタまたは参照であり、 expression の型が Derived へのポインタまたは参照であり、 BaseDerived の一意かつアクセス可能な基底である場合、結果は expression が指しているまたは表している Derived オブジェクト内の Base クラス部分オブジェクトへのポインタまたは参照です (ノート: 暗黙の変換および static_cast も同様にこの変換を行うことができます)。
4) expression多相型へのポインタで、 new_typevoid へのポインタの場合、結果は expression が指しているまたは参照している最も派生したオブジェクトへのポインタです。
5) expression多相型 Base へのポインタで、 new_typeDerived 型へのポインタまたは参照の場合は、実行時のチェックが行われます。
a) expression が指しているまたは表している最も派生したオブジェクトが調べられます。 そのオブジェクトにおいて、 expressionDerived のパブリックな基底を指しているまたは参照している場合、かつ、 expression が指しているまたは表している部分オブジェクトから派生した Derived 型の部分オブジェクトが唯一の場合、キャストの結果はその Derived 部分オブジェクトを指すまたは参照します (これは「ダウンキャスト」と言います)。
b) そうでなく、 expression が最も派生したオブジェクトのパブリックな基底を指しているまたは参照しており、かつ、同時に、その最も派生したオブジェクトが曖昧でないパブリックな Derived 型の基底クラスを持つ場合、キャストの結果はその Derived を指すまたは参照します (これは「クロスキャスト」と言います)。
c) そうでなければ、実行時のチェックは失敗します。 dynamic_cast がポインタに対して使用された場合は、 new_type 型のヌルポインタ値が返されます。 参照に対して使用された場合は、例外 std::bad_cast が投げられます。
6) dynamic_cast が (直接または間接的に) コンストラクタまたはデストラクタ内で使用され、 expression が現在構築中または破棄中のオブジェクトを参照しているときは、そのオブジェクトが最も派生したオブジェクトとみなされます。 new_type がそのコンストラクタまたはデストラクタの自分のクラスまたはその基底のいずれかへのポインタまたは参照でない場合、動作は未定義です。

他のキャスト式と同様に、

  • new_type が左辺値参照型の場合、結果は lvalue です (expression は lvalue でなければなりません)。
  • new_type が右辺値参照型の場合、結果は xvalue です (expressionlvalue でも rvalue でも構いません (C++17以前)完全クラス型の glvalue でなければなりません (prvalue は具体化されます) (C++17およびそれ以降))。
  • new_type がポインタ型の場合、結果は prvalue です。

[編集] ノート

ダウンキャストは static_cast を用いても行うことができ、それによって実行時のチェックのコストを回避することができますが、これは expression の指すオブジェクトが間違いなく Derived であることを (他の何らかのロジックによって) 保証できる場合にのみ安全です。

[編集] キーワード

dynamic_cast

[編集]

#include <iostream>
 
struct V {
    virtual void f() {};  // 実行時チェック付きの dynamic_cast を使用するために
                          // 多相でなければなりません。
};
struct A : virtual V {};
struct B : virtual V {
  B(V* v, A* a) {
    // 構築中のキャスト (下の D のコンストラクタ内の呼び出しを参照してください)。
    dynamic_cast<B*>(v); // well-defined。 v は V* 型 で、 V は B の基底なので、結果は B* です。 
    dynamic_cast<B*>(a); // 未定義動作。 a は A* 型であり、 A は B の基底ではありません。
  }
};
struct D : A, B {
    D() : B(static_cast<A*>(this), this) { }
};
 
struct Base {
    virtual ~Base() {}
};
 
struct Derived: Base {
    virtual void name() {}
};
 
int main()
{
    D d; // 最も派生したオブジェクト。
    A& a = d; // アップキャスト。 dynamic_cast を使っても構いませんが、必要はありません。
    D& new_d = dynamic_cast<D&>(a); // ダウンキャスト。
    B& new_b = dynamic_cast<B&>(a); // クロスキャスト。
 
 
    Base* b1 = new Base;
    if(Derived* d = dynamic_cast<Derived*>(b1))
    {
        std::cout << "downcast from b1 to d successful\n";
        d->name(); // 呼んでも安全です。
    }
 
    Base* b2 = new Derived;
    if(Derived* d = dynamic_cast<Derived*>(b2))
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // 呼んでも安全です。
    }
 
    delete b1;
    delete b2;
}

出力:

downcast from b2 to d successful

[編集] 関連項目