C++ プログラミングガイド |
第 7 章
キャスト演算
この章では、C++ 標準で新しいキャスト演算子である、
const_cast
、reinterpret_cast
、static_cast
、dynamic_cast
について説明します。キャストは、オブジェクトまたは値の型を別の型に変換します。新しいキャスト演算
C++ 標準では、以前のキャスト演算よりキャストの制御が優れた新しいキャスト演算を定義しています。dynamic_cast<> 演算子では、多様なクラスへのポインタの実際の型を調べることができます。古い形式のキャストを検索するには構文解析が必要ですが、新しい形式のキャストはテキストエディタを使用してすべて検索できます (
_cast
を検索する)。それ以外では、これらの新しいキャストはすべて、古いキャスト表記で許可されたキャスト演算の一部を実行します。たとえば、const_cast<int*>v は (int*)v と書くことができます。これらの新しいキャストは、利用できる演算の種類を簡潔に分類してプログラマの意図をより明確に示し、コンパイラがより効率のよい検査を行うようにします。
const
キャスト式 const_cast<T>(v) を使用して、ポインタまたは参照の
const
修飾子またはvolatile
修飾子を変更することができます(新しい形式のキャストの内、const
修飾子を削除できるのはconst_cast<>
のみ)。T
はポインタ、参照、またはメンバー型へのポインタでなければなりません。
解釈を変更するキャスト
式 reinterpret_cast<T>(v) は式 v の値の解釈を変更します。この式は、ポインタ型と整数型の間、2 つの無関係なポインタ型の間、ポインタ型からメンバー型へ、ポインタ型から関数型へ、という各種の変換に使用できます。
reinterpret_cast
演算子を使用すると、未定義の結果または実装に依存しない結果を出すことがあります。次に、確実な動作について説明します。
- データオブジェクトまたは関数へのポインタ (メンバーへのポインタは除く) は、それを十分保持できる大きさの任意の整数型に変換できます (
long
型は十分大きいため、Sun WorkShop C++ がサポートするアーキテクチャでは常にポインタ値を保持できます)。元の型に戻しても、値は元の値と同じになります。- (非メンバー) 関数へのポインタは、別の (非メンバー) 関数型へのポインタに変換できます。元の型に戻しても、値は元の値と同じになります。
- 新しい型が元の型よりも厳しい整列条件を持たない場合、オブジェクトへのポインタは別のオブジェクト型へのポインタに変換できます。元の型に戻しても、値は元の値と同じになります。
reinterpret_cast
演算子を使用して型「T1 のポインタ」の式を型「T2 のポインタ」に変換できる場合、型 T1 の左辺値は型「T2 の参照」に変換できます。- T1 と T2 の両方が関数型であるか両方がオブジェクト型である場合、「型 T1 の X のメンバーを指すポインタ」型の右辺値は、「型 T2 の Y のメンバーを指すポインタ」型の右辺値に明示的に変換できます。
- (変換が許可されている場合) ある型のヌルポインタは別の型のヌルポインタに変換された後もヌルポインタのままです。
reinterpret_cast
演算子を使用して、const
をconst
でない型にキャストすることはできません。このようにキャストするにはconst
キャストを使用します。reinterpret_cast
演算子を使用して、ポインタと、同じクラス階層に存在する別のクラスの間の変換を行うことはできません。このように変換するには、静的キャストまたは動的キャストを使用します (reinterpret_cast
は必要があっても調整は行わない)。次にこの例を示します。
静的キャスト
式 static_cast<T>(v) は式の値 v を型 T の値に変換します。この式は、暗黙的に実行されるすべての型変換に使用できます。さらに、いかなる値でも void にキャストすることができ、いかなる暗黙的型変換でも、そのキャストが旧式のキャストと同様に正当である限り、反転させることができます。
static_cast
演算子を使用して、const
をconst
以外の型にするようなキャストを行うことはできません。階層の下位に (基底から派生ポインタまたは参照へ) キャストするにはstatic_cast
を使用できますが、変換は検証されず、結果は使用できない場合があります。抽象基底クラスから下位へのキャストには、static_cast
は使用できません。
動的キャスト
クラスへのポインタ (または参照) は、そのクラスから派生されたすべてのクラスを実際に指す (参照する) ことができます。場合によっては、オブジェクトの完全派生クラス、またはその完全なオブジェクトの他のサブオブジェクトへのポインタを得る方が望ましいことがあります。動的キャストによってこれが可能になります。
注 - 互換モード (-compat[=4]
) でコンパイルする場合、プログラムが動的キャストを使用している場合は、-features=rtti
を付けてコンパイルする必要があります。
動的な型のキャストは、あるクラス T1 へのポインタ (または参照) を別のクラス T2 のポインタ (または参照) に変換します。T1 と T2 は、同じ階層内になければなりません。両クラスとも (公開派生を介して) アクセス可能でなければならず、変換はあいまいであってはなりません。また、変換が派生クラスからその基底クラスの 1 つに対するものでないかぎり、T1 と T2 の両方が入った階層の最小の部分は多相性がなければなりません (少なくとも仮想関数が 1 つ存在すること)。
式
dynamic_cast
<T>(v) では、v はキャストされる式であり、T はキャストの対象となる型です。T は完全なクラス型 (定義が参照できるもの) へのポインタまたは参照であるか、あるいは「cv void へのポインタ」でなければなりません。ここで cv は空の文字列、const
、volatile
、const
volatile
のいずれかです。階層の上位にキャストする
階層の上位にキャストする場合で、v が指す (参照する) 型の基底クラスを T が指す (あるいは参照する) 場合、変換は
static_cast
<T>(v) で行われるものと同じです。
void*
にキャストするT が
void*
の場合、結果はオブジェクト全体のポインタになります。つまり、v はあるオブジェクト全体の基底クラスの 1 つを指す可能性があります。この場合、dynamic_cast<void*>
(v)の結果は、v をオブジェクト全体の型 (種類は問わない) に変換した後で
void*
に変換した場合と同じです。
void*
にキャストする場合、階層に多相性がなければなりません (仮想関数が存在すること)。結果は実行時に検証されます。階層の下位または全体にキャストする
階層の下位または全体にキャストする場合、階層に多相性がなければなりません (仮想関数を持つ必要がある)。結果は実行時に検証されます。
階層の下位または全体にキャストする場合、v から T に変換できないことがあります。たとえば、試行された変換があいまいであったり、T に対するアクセスが不可能であったり、あるいは必要な型のオブジェクトを v が指さない (あるいは参照しない) 場合がこれに当たります。実行時検査が失敗し、T がポインタ型である場合、キャスト式の値は型 T のヌルポインタです。T が参照型の場合、何も返されず (C++ にはヌル参照は存在しない)、標準例外
std::bad_cast
が送出されます。
しかし、次の例は、基底クラス B にアクセスできないために失敗します。
1 つの基底クラスについて仮想継承と多重継承が存在する場合には、実際の動的キャストは一意の照合を識別することができなければなりません。もし照合が一意でないならば、そのキャストは失敗します。たとえば、下記の追加クラス定義が与えられたとします。
class AB_B : public AB, public B { };class AB_B__AB : public AB_B, public AB { };
dynamic_cast のエラー時のヌル (NULL) ポインタの戻り値は、コード中の 2 つのブロック (1 つは型推定が正しい場合にキャストを処理するためのもの、もう 1 つは正しくない場合のもの) の間の条件として役立ちます。
互換モード (
-compat[=4]
) では、-features=rtti
コンパイラオプションによって実行時の型情報が有効になっていないと、コンパイラはdynamic_cast
をstatic_cast
に変換し、警告メッセージを出します (「RTTI オプション」を参照)。実行時型情報が無効にされている場合、すなわち -features=no%rtti の場合には 、コンパイラは dynamic_cast を static_cast に変換し、警告を発行します。参照型への動的キャストを行う場合は、そのキャストが実行時に無効であると判明したときに送出される例外が必要です。
動的キャストは必然的に、仮想関数による変換のような適切な設計パターンより遅くなります。Erich Gamma 著 (ソフトバンク)『オブジェクト指向における再利用のためのデザインパターン』を参照してください。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |