C++ でダイナミックキャストを使用する
この記事では、C++ でダイナミックキャストを利用する方法について複数のメソッドを紹介します。
基底クラスポインタから派生クラスへの変換に dynamic_cast
を使用する
dynamic_cast
を使用すると、プログラマは継承階層を越えてクラスへのポインタや参照を変換することができます。例えば、基底クラスポインタを派生クラスポインタにキャストして、プログラマが派生クラスのメンバ関数を呼び出すことができます。
dynamic_cast
はランタイム型情報(RTTI)機能の一部であり、コンパイル時ではなく実行時にオブジェクトの型にアクセスする方法を提供します。
なお、dynamic_cast
は int
や float
のようなプリミティブ型間の変換には使えないことに注意してください。さらに、dynamic_cast
は基底クラスに少なくとも 1つの仮想メンバ関数が含まれている場合にのみ使用すべきです。次の例では、新しい Base
クラスポインタを宣言し、それを Derived
クラスへの新しいポインタにキャストします。dynamic_cast
は null ポインタを返すので、もしキャストに失敗した場合は、if
文の中に条件として式を記述することができます。
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
struct Base {
virtual ~Base() = default;
};
struct Derived : public Base {};
int main() {
Base *bp = new Derived;
if (Derived *dp = dynamic_cast<Derived *>(bp)) {
cout << "Successful cast - can use the pointer to 'Derived' object dp"
<< endl;
}
delete bp;
return EXIT_SUCCESS;
}
出力:
Successful cast - can use the pointer to 'Derived' object dp
プログラマは if
セクションスコープ内のオブジェクトに安全にアクセスし、必要に応じて Derived
クラスのメンバメソッドを呼び出すことができます。ただし、Derived
クラスの型を Base
にキャストしているので、13 行目では new
演算子の後に Derived
を指定しています。
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
struct Base {
virtual ~Base() = default;
};
struct Derived : public Base {};
int main() {
Base *bp = new Base;
if (Derived *dp = dynamic_cast<Derived *>(bp)) {
cout << "Successful cast - can use the pointer to 'Derived' object dp"
<< endl;
}
delete bp;
return EXIT_SUCCESS;
}
RTTI の機能のもう一つの部分は typeid
演算子で、これは与えられた式の型を返すものです。これは、次のコードサンプルで示されているように、複数の式の型を比較するために利用することができます。なお、typeid
演算子を利用する際には、<typeinfo>
ヘッダを含める必要があります。
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
struct Base {
virtual ~Base() = default;
};
struct Derived : public Base {};
int main() {
Base *bp = new Derived;
if (Derived *dp = dynamic_cast<Derived *>(bp)) {
cout << "Successful cast - can use the pointer to 'Derived' object dp"
<< endl;
if (typeid(*bp) == typeid(*dp)) {
cout << "bp and dp are of same type" << endl;
}
}
delete bp;
return EXIT_SUCCESS;
}
出力:
Successful cast - can use the pointer to 'Derived' object dp
bp and dp are of same type