ここではstatic_cast<>
、dynamic_cast<>
特にポインターに関連する概要を示します。これは 101 レベルの要約に過ぎず、すべての複雑さを網羅しているわけではありません。
static_cast< Type* >(ptr)
これはポインタを受け取り、ptr
それを type のポインタに安全にキャストしようとしますType*
。このキャストはコンパイル時に行われます。型が関連している場合にのみキャストを実行します。型が関連していない場合は、コンパイラ エラーが発生します。例えば:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast< Type* >(ptr)
ptr
これは再びポインターを取り込もうとし、安全に type のポインターにキャストしようとしますType*
。ただし、このキャストはコンパイル時ではなく実行時に実行されます。これはランタイム キャストであるため、特にポリモーフィック クラスと組み合わせると便利です。実際、場合によっては、キャストが合法的であるためにクラスがポリモーフィックである必要があります。
キャストは、ベースから派生 (B2D) または派生からベース (D2B) の 2 つの方向のいずれかに進むことができます。D2B キャストが実行時にどのように機能するかを確認するのは簡単です。ptr
から派生したType
か、そうでないかのどちらかです。D2B dynamic_cast<> の場合、ルールは単純です。何かを他の何かにキャストしようとすることができptr
、実際に から派生したものである場合はType
、Type*
からポインターが返されdynamic_cast
ます。そうしないと、NULL ポインターが返されます。
しかし、B2D キャストはもう少し複雑です。次のコードを検討してください。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main()
返されるオブジェクトの種類がわからないCreateRandom()
ため、C スタイルのキャストBar* bar = (Bar*)base;
は明らかに型安全ではありません。どうすればこれを修正できますか? 1 つの方法は、bool のような関数を基本クラスに追加して、fromおよびfrom からAreYouABar() const = 0;
返すことです。しかし、別の方法があります: 使用:true
Bar
false
Foo
dynamic_cast<>
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
キャストは実行時に実行され、オブジェクトを照会して (今のところ方法について心配する必要はありません)、探している型であるかどうかを尋ねます。そうであればdynamic_cast<Type*>
、ポインタを返します。それ以外の場合は NULL を返します。
このベースから派生へのキャストが を使用して機能するためにはdynamic_cast<>
、Base、Foo、および Bar が、標準でポリモーフィック タイプと呼ばれるものでなければなりません。ポリモーフィック型であるためには、クラスに少なくとも 1 つのvirtual
関数が必要です。クラスがポリモーフィック型でない場合、ベースから派生への使用はdynamic_cast
コンパイルされません。例:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
仮想 dtor などの仮想関数を base に追加すると、Base と Der の両方のポリモーフィック型が作成されます。
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}