dynamic_cast 変換
From cppreference.com
継承階層を上下左右に安全にポインタと参照を変換します。
目次 |
[編集] 構文
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へのポインタ」であり、BaseがDerivedの基底クラスである場合、結果は- 式がヌルポインタ値の場合はヌルポインタ値、または
- それ以外の場合は、式が指す
DerivedオブジェクトのユニークなBaseサブオブジェクトへのポインタ。言い換えれば、dynamic_cast を使用して、派生から基底へポインタをアップキャストできます。暗黙の変換とstatic_cast もこの変換を実行できます。
3) ターゲット型が「(おそらくcv修飾された)
Baseへの参照」であり、式の型が「(おそらくcv修飾された) Derived」であり、BaseがDerivedの基底クラスである場合、結果は式が参照するDerivedオブジェクトのユニークなBaseサブオブジェクトです。言い換えれば、dynamic_cast を使用して、派生から基底へ参照をアップキャストできます。暗黙の変換とstatic_cast もこの変換を実行できます。4) それ以外の場合、式は寿命内、または構築中または破棄中のポリモーフィック型のオブジェクトへのポインタまたは参照でなければならず、その型は式の型と類似している必要があります (そうでなければ未定義動作)
b) それ以外の場合、式が指す/参照するオブジェクトが、ターゲット型が指す/参照する型
Targetに変換できるかどうかの実行時チェックが適用されます。i) 式が指す/参照する最も派生したオブジェクト内で、式が
Targetオブジェクトの公開基底クラスサブオブジェクトを指す/参照し、式が指す/参照するサブオブジェクトから派生するTarget型のオブジェクトが1つしかない場合、結果はそのTargetオブジェクトを指す/参照します。言い換えれば、dynamic_cast を使用して、基底から派生へポインタ/参照をダウンキャストできます。ii) それ以外の場合、式が最も派生したオブジェクトの公開基底クラスサブオブジェクトを指す/参照し、最も派生したオブジェクトの型が
Target型の曖昧でない公開基底クラスを持つ場合、結果は最も派生したオブジェクトのTargetサブオブジェクトを指す/参照します。言い換えれば、dynamic_cast を使用して、同じ基底から派生した2つの型の間でポインタ/参照をクロスキャスト (またはサイドキャスト) できます。iii) それ以外の場合、実行時チェックは失敗します。
- ターゲット型がポインタ型の場合、結果はターゲット型のヌルポインタ値です。
- ターゲット型が参照型の場合、
std::bad_cast型のハンドラと一致する型の例外がスローされます。
dynamic_cast がコンストラクタまたはデストラクタ内で (直接的または間接的に) 使用され、式が現在構築中/破棄中のオブジェクトを参照している場合、そのオブジェクトは最も派生したオブジェクトと見なされます。ターゲット型がコンストラクタ/デストラクタ自身のクラスまたはその基底のポインタまたは参照でない場合、動作は未定義です。
他のキャスト式と同様に、結果は
|
(C++11まで) |
|
(C++11以降) |
[編集] 備考
ダウンキャストはstatic_cast でも実行できます。これにより実行時チェックのコストを回避できますが、プログラムが (他のロジックを通じて) 式が指すオブジェクトが確実にDerivedであることを保証できる場合にのみ安全です。
dynamic_cast の一部の形式は、実行時型情報 (RTTI)、つまりコンパイルされたプログラム内の各ポリモーフィッククラスに関する情報に依存します。コンパイラには通常、この情報の含めるのを無効にするオプションがあります。
[編集] キーワード
[編集] 例
このコードを実行
#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]