概要
C++には独自のキャストがあり、詳細は以下のとおり。
static_cast
静的キャストで、一般的なキャストに用いる。int ⇔ long, int ⇔ double など。また、列挙型を int型にする場合等にも用いる。キャストできない場合は、コンパイル時にエラーとなる。ポインタ型同士のキャストは不可で、ポインタ同士のキャストには、reinterpret_castを用いる。
例)
int n;
double f = 12.4;
n = static_cast<int>(f);
dynamic_cast
動的キャストと呼ばれ、安全にダウンキャストする為に用いる。もし不正なポインタでダウンキャストした場合、キャスト結果が NULL になり、その結果をチェックすれば、キャストの失敗を検出できる。dynamic_cast は、コンパイル時ではなく、実行時に判断することが、他のキャストとは全く異なるところである。dynamic_cast は、実行時の成否判定に時間が要する為、処理時間を浪費する。よって、数回呼び出す程度では問題ありませんが、非常に多くの回数が実行されるループ内等では、使用しない方がいい。
例)
CSampleA sampA;
CSampleB* pSampB = dynamic_cast<CSampleB*)(&sampA);
アップキャスト
継承関係の下から上へ向かうキャスト。
アップキャストは安全に行えることが保証されるので、明示的にキャストを行わなくても、暗黙のうちに行える。
ダウンキャスト
継承関係の上から下へ向かうキャスト。アップキャストとは異なり、ダウンキャストは危険さを伴う。なぜなら、サブクラス側には、スーパークラス側が持たないメンバが含まれている可能性がある。
ダウンキャスト自体を避けるべきですが、必要な場合には、dynamic_cast を用いる。
const_cast
constやvolatileを無効化するために用いる。これ以外のキャストは、コンパイルエラーとなる。
例)
const int* cp;
int* p = const_cast<int*>( cp );
但し、書き換え禁止の為、const属性が付与されてるので、それを外すことが危険な動作であることは留意すること。あくまでも、constやvolatile属性を外すことしかできないので、const void*型から int*型への変換のように、ポインタ型の変換も必要な場合等には、後述するreinterpret_castとの併用が必要となる。
例)
const void* cp; // どこかを指しているポインタ
int* pnum = reinterpret_cast<int*>( const_cast<void*>( cp ) ); // 2段階のキャスト
非常に危険ですが、必要となる場面もある。
reinterpret_cast
再解釈キャストは、根本的に異なる型同士のキャストに用いる。
例えば、ポインタ型同士の変換や、int型の変数をポインタ型に変換する場合など。この変換がどのように行われるかは、環境に大きく依存する為、別の環境へプログラムを移植する場合に問題になる可能性あるので、本来ならあまり使用すべきではない。
例)
int n = 123;
CSample* p = reinterpret_cast<CSample*>(n);
ある型を指すポインタを、void*型に変換する場合、明示的なキャストは必要なく、暗黙のうちに行われる。逆に、void*型を具体的な型を指すポインタに変換する場合、キャストが必要になるが、この場合のキャストは、static_cast で構わない。C言語では、void*型からの変換は暗黙的に行えるが、 C++ では行えないという違いがある。
また、もし、int*型から float*型のように、異なるポインタ型のキャストが必要なら、reinterpret_cast を使うよりも、 static_cast で済むように工夫した方がいい。つまり、void*型への変換に明示的なキャストが不要であることと、void*型から任意のポインタ型へは static_cast が使えることを利用する。
例)
int* pi = #
void* pv = pi; // 一旦、void*型にする
float* pf = static_cast<float*>( pv ); // static_cast で float*型へ
コメント
最終更新:2010年09月28日 18:06