dynamic_cast 演算子 (C++ のみ)

dynamic_cast 演算子は、以下の種類の変換を実行時に検査します。
  • 基底クラスを指すポインターから、派生クラスを指すポインター
  • 基底クラスを参照する左辺値から、派生クラスを参照する左辺値
  • C++11基底クラスを参照する xvalue から、派生クラスを参照する右辺値C++11
それによって、プログラムはクラス階層を安全に使用することができます。 この演算子と typeid 演算子は、C++ でのランタイム型情報 (RTTI) サ ポートを提供します。
構文図を読む構文図をスキップする
dynamic_cast 演算子の構文 

>>-dynamic_cast--<--T-->--(--v--)------------------------------><

C++11右不等号括弧の機能により、2 つの連続する > トークンの代わりに >> トークンを使用して、template_iddynamic_cast 演算子の T として指定することができます。詳しくは、クラス・テンプレート (C++ のみ)を参照してください。C++11

dynamic_cast<T>(v) は、式 v を型 T に変換します。 型 T は、完全クラス型を指すポインターまたは参照、 あるいは void を指すポインターでなければなりません。

dynamic_cast<T>(v) という式には、以下の規則が適用されます。
  • T がポインター型である場合は、v は、C++11(prvalue)C++11 右辺値でなければならず、dynamic_cast<T>(v) は、C++11(prvalue)C++11T の右辺値になります。
  • T が左辺値参照型である場合は、v が左辺値でなければならず、dynamic_cast<T>(v)T によって参照される型の左辺値になります。
  • C++11T が 右辺値参照型である場合、dynamic_cast<T>(v)T によって 参照される型の xvalue になります。C++11

T がポインターであって、dynamic_cast 演算子が失敗した場合、 演算子は、型 T の NULL ポインターを戻します。 T が参照であって、dynamic_cast 演算子が失敗した場合、 演算子は、例外 std::bad_cast を throw します。 このクラスは、標準ライブラリー・ヘッダー <typeinfo> の中で検出することができます。

dynamic_cast 演算子は、ランタイム型情報 (RTTI) が 生成される必要があります。その情報は、コンパイラー・オプションによっ てコンパイル時に明示的に指定しなければなりません。

T が void ポインターの場合、dynamic_cast は、v が指すオブジェクトの開始アドレスを戻します。 次の例は、このことを示しています。
#include <iostream>
using namespace std;

struct A {
  virtual ~A() { };
};

struct B : A { };

int main() {
  B bobj;
  A* ap = &bobj;
  void * vp = dynamic_cast<void *>(ap);
  cout << "Address of vp  : " << vp << endl;
  cout << "Address of bobj: " << &bobj << endl;
}
この例の場合、出力結果は次のようになります。 vp および &bobj の両方とも同じアドレスを参照します。
Address of vp  : 12FF6C
Address of bobj: 12FF6C

dynamic_cast 演算子の主目的は、 型が異なっても支障のないダウンキャスト を実行することです。 ダウンキャストとは、クラス AB の基底クラスである場合に、クラス A を指すポインターまたは参照をクラス B を指すポインターまたは参照に変換することです。 ダウンキャストの問題は、型 A* のポインターが、B のオブジェクトに属する型 A の基底クラス・サブオブジェクトでも、B から派生したクラスでもないオブジェクトを指している可能性があることですdynamic_cast 演算子を使用すると、 クラス A を指すポインターをクラス B を指すポインターに変換する場合に、 前者が指す型 A のオブジェクトが、 B のオブジェクトまたは基底クラス・サブオブジェクトとして B から派生したクラスのオブジェクトに属することが保証されます。

以下の例は、dynamic_cast 演算子の使用法を示したものです。
#include <iostream>
using namespace std;

struct A {
  virtual void f() { cout << "Class A" << endl; }
};

struct B : A {
  virtual void f() { cout << "Class B" << endl; }
};

struct C : A {
  virtual void f() { cout << "Class C" << endl; }
};

void f(A* arg) {
  B* bp = dynamic_cast<B*>(arg);
  C* cp = dynamic_cast<C*>(arg);

  if (bp)
    bp->f();
  else if (cp)
    cp->f();
  else
    arg->f();
};

int main() {
  A aobj;
  C cobj;
  A* ap = &cobj;
  A* ap2 = &aobj;
  f(ap);
  f(ap2);
}
上記の例の出力は、次のとおりです。
Class C
Class A
関数 f() は、ポインター arg が、型 AB、 または C のオブジェクトを指すかどうかを判別します。 関数は、dynamic_cast 演算子を使用して、arg を、型 B のポインターへ、 次に型 C のポインターへ変換しようと試みることによって、この判別を行います。 dynamic_cast 演算子が正常に行われると、arg によって表されるオブジェクトを指すポインターを戻します。 dynamic_cast が失敗すると、0 が戻されます。

downcast は、ポリモアフィック・クラスにおいてのみ、dynamic_cast 演算子を使用して、 実行することができます。 上記の例では、クラス A は、仮想関数をもっているので、 すべてのクラスはポリモアフィックです。 dynamic_cast 演算子は、 ポリモアフィック・クラスから生成されたランタイム時の型情報を使用します。