名前空間
変種
操作

dynamic_cast 変換

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

継承階層を上下左右に安全にポインタと参照を変換します。

目次

[編集] 構文

dynamic_cast< ターゲット型 >( )
ターゲット型 - 完全なクラス型へのポインタ、完全なクラス型への参照、または (オプションでcv修飾された) void へのポインタ
- ターゲット型が参照型の場合は完全なクラス型の左辺値(C++11まで)glvalue(C++11以降)ターゲット型がポインタ型の場合は完全なクラス型へのポインタのprvalue

[編集] 説明

説明の便宜上、「またはその結果がTへの参照である」とは、「それは型Tのglvalueである」ことを意味します。これはdecltypeの慣例に従います(C++11以降)

定数性 (または揮発性) を除去するような変換を除き、dynamic_cast でできる変換は以下の通りです。

1) の型がターゲット型と厳密に同じか、またはターゲット型のcv修飾が少ない場合、結果はターゲット型の値になります。言い換えれば、dynamic_cast を使用して定数性を追加することができます。暗黙の変換とstatic_cast もこの変換を実行できます。
2) ターゲット型が「(おそらくcv修飾された) Baseへのポインタ」であり、の型が「(おそらくcv修飾された) Derivedへのポインタ」であり、BaseDerivedの基底クラスである場合、結果は
  • がヌルポインタ値の場合はヌルポインタ値、または
  • それ以外の場合は、が指すDerivedオブジェクトのユニークなBase サブオブジェクトへのポインタ。言い換えれば、dynamic_cast を使用して、派生から基底へポインタをアップキャストできます。暗黙の変換とstatic_cast もこの変換を実行できます。
3) ターゲット型が「(おそらくcv修飾された) Baseへの参照」であり、の型が「(おそらくcv修飾された) Derived」であり、BaseDerivedの基底クラスである場合、結果はが参照するDerivedオブジェクトのユニークなBaseサブオブジェクトです。言い換えれば、dynamic_cast を使用して、派生から基底へ参照をアップキャストできます。暗黙の変換とstatic_cast もこの変換を実行できます。
4) ポリモーフィック型のヌルポインタ値である場合、結果はターゲット型のヌルポインタ値です。
4) それ以外の場合、寿命内、または構築中または破棄中のポリモーフィック型のオブジェクトへのポインタまたは参照でなければならず、その型はの型と類似している必要があります (そうでなければ未定義動作)
a) が (おそらくcv修飾された) void へのポインタである場合、結果はが指す最も派生したオブジェクトへのポインタです。
b) それ以外の場合、が指す/参照するオブジェクトが、ターゲット型が指す/参照する型Targetに変換できるかどうかの実行時チェックが適用されます。
i) が指す/参照する最も派生したオブジェクト内で、Targetオブジェクトの公開基底クラスサブオブジェクトを指す/参照し、が指す/参照するサブオブジェクトから派生するTarget型のオブジェクトが1つしかない場合、結果はそのTargetオブジェクトを指す/参照します。言い換えれば、dynamic_cast を使用して、基底から派生へポインタ/参照をダウンキャストできます。
ii) それ以外の場合、が最も派生したオブジェクトの公開基底クラスサブオブジェクトを指す/参照し、最も派生したオブジェクトの型がTarget型の曖昧でない公開基底クラスを持つ場合、結果は最も派生したオブジェクトのTargetサブオブジェクトを指す/参照します。言い換えれば、dynamic_cast を使用して、同じ基底から派生した2つの型の間でポインタ/参照をクロスキャスト (またはサイドキャスト) できます。
iii) それ以外の場合、実行時チェックは失敗します。
  • ターゲット型がポインタ型の場合、結果はターゲット型のヌルポインタ値です。
  • ターゲット型が参照型の場合、std::bad_cast 型のハンドラと一致する型の例外がスローされます。

dynamic_cast がコンストラクタまたはデストラクタ内で (直接的または間接的に) 使用され、が現在構築中/破棄中のオブジェクトを参照している場合、そのオブジェクトは最も派生したオブジェクトと見なされます。ターゲット型がコンストラクタ/デストラクタ自身のクラスまたはその基底のポインタまたは参照でない場合、動作は未定義です。

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

  • ターゲット型が参照型の場合は左辺値
  • ターゲット型がポインタ型の場合は右辺値
(C++11まで)
  • ターゲット型が左辺値参照型の場合は左辺値 (は左辺値である必要があります)
  • ターゲット型が右辺値参照型の場合はxvalue (は完全なクラス型の左辺値または右辺値である場合があります(C++17まで)glvalueである必要があります (prvalueは具現化されます)(C++17以降))
  • ターゲット型がポインタ型の場合はprvalue
(C++11以降)

[編集] 備考

ダウンキャストはstatic_cast でも実行できます。これにより実行時チェックのコストを回避できますが、プログラムが (他のロジックを通じて) が指すオブジェクトが確実にDerivedであることを保証できる場合にのみ安全です。

dynamic_cast の一部の形式は、実行時型情報 (RTTI)、つまりコンパイルされたプログラム内の各ポリモーフィッククラスに関する情報に依存します。コンパイラには通常、この情報の含めるのを無効にするオプションがあります。

[編集] キーワード

dynamic_cast

[編集]

#include <iostream>
 
struct V
{
    virtual void f() {} // must be polymorphic to use runtime-checked dynamic_cast
};
 
struct A : virtual V {};
 
struct B : virtual V
{
    B(V* v, A* a)
    {
        // casts during construction (see the call in the constructor of D below)
        dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
        dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of 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; // the most derived object
    A& a = d; // upcast, dynamic_cast may be used, but unnecessary
 
    [[maybe_unused]]
    D& new_d = dynamic_cast<D&>(a); // downcast
    [[maybe_unused]]
    B& new_b = dynamic_cast<B&>(a); // sidecast
 
    Base* b1 = new Base;
    if (Derived* d = dynamic_cast<Derived*>(b1); d != nullptr)
    {
        std::cout << "downcast from b1 to d successful\n";
        d->name(); // safe to call
    }
 
    Base* b2 = new Derived;
    if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr)
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // safe to call
    }
 
    delete b1;
    delete b2;
}

出力

downcast from b2 to d successful

[編集] 欠陥報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 1269 C++11 ターゲット型が右辺値参照型の場合、xvalueに対して実行時チェックが実行されなかった
expression s if target-type is an rvalue reference type
実行された
CWG 2861 C++98 が型にアクセスできないオブジェクトを指す/参照する可能性があった この場合、動作は未定義である

[編集] 参照

  • C++23標準 (ISO/IEC 14882:2024)
  • 7.6.1.7 Dynamic cast [expr.dynamic.cast]
  • C++20 standard (ISO/IEC 14882:2020)
  • 7.6.1.6 Dynamic cast [expr.dynamic.cast]
  • C++17 standard (ISO/IEC 14882:2017)
  • 8.2.7 Dynamic cast [expr.dynamic.cast]
  • C++14 standard (ISO/IEC 14882:2014)
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++11 standard (ISO/IEC 14882:2011)
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++98 標準 (ISO/IEC 14882:1998)
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++03 標準 (ISO/IEC 14882:2003)
  • 5.2.7 Dynamic cast [expr.dynamic.cast]

[編集] 関連項目

English 日本語 中文(简体) 中文(繁體)