キャスト演算子


動的キャスト

C++では、C言語の型キャストをそのまま使うことができますが
それ以外に、C++特有の型キャスト演算子が用意されています

その中でも、とくに重要なのが dynamic_cast でしょう
この演算子は、C++のポリモーフィッククラスに対応しているもので
実行時型変換を行い、有効であれば型を変換します

dynamic_cast < type-id > ( expression )

type-id には、変換する目的の型を指定します
必ずポインタ型か参照でなければいけません
expression は、目的の型に変換する式を指定します
type-idがポインタ型ならポインタ、参照ならば変数を指定します
#include<iostream>
using namespace std;

class Kitty {
public:
	virtual void func() { cout << "Kitty on your lap\n"; }
};

class Chobits : public Kitty {
public:
	void func() { cout << "Chobits\n"; }
} obj ;

int main() {
	Kitty *po = dynamic_cast <Kitty *> (&obj);
	po->func();
	return 0;
}
Kitty の派生クラス Chobits のオブジェクトを、Kitty のポインタ型に型キャストしています
派生クラスのオブジェクトは基本クラスのポインタ型にキャストできることは説明しましたね
これは、暗黙的にキャストできるのこの演算子を使いませんでした
もちろん、このように dynamic_cast 演算子を使っても問題ありません

このように、派生クラスから基本クラスの型への変換をアップキャストと呼びます
これは、この演算子を使わなくても暗黙的に行うことができました

しかし、dynamic_cast 演算子はこの逆の変換を行うこともできます
つまり、基本クラス型のポインタを派生クラスのポインタ方に変換します
当然、この動作は基本クラス型のポインタが指すオブジェクトが
目的の派生クラスのオブジェクトでなければいけません
#include<iostream>
using namespace std;

class Kitty {
public:
	virtual void func() { cout << "Kitty on your lap\n"; }
};

class Chobits : public Kitty {
public:
	void func() {}
	void toString() {  cout << "Chobits\n"; }
} obj ;

int main() {
	Kitty *tmp = &obj;
	Chobits *po = dynamic_cast <Chobits *> (tmp);

	po->toString();	
	return 0;
}
このプログラムでは、一度アップキャストした Kitty * 型のポインタを
元の派生クラス Chobits * へ変換しています

アップキャストに対して、基本クラスから派生クラスの型に変換する
上のプログラムのような動作をダウンキャストと呼びます

ダウンキャストは基本クラスのポインタが指すオブジェクトが
目的の派生クラスのオブジェクトでなくてはいけません
ただし、このチェックはコンパイル時ではなく実行時に判別しなくてはなりません

dynamic_cast 演算子は、型変換時に型のチェックを行い
可能であれば上のプログラムのように変換し、適切でなければ NULL を返します
#include<iostream>
using namespace std;

class Kitty {
public:
	virtual void func() { cout << "Kitty on your lap\n"; }
} obj ;

class Chobits : public Kitty {
public:
	void toString() {  cout << "Chobits\n"; }
};

int main() {
	Chobits *po = dynamic_cast <Chobits *> (&obj);

	if (!po) {
		cout << "型キャストに失敗しました";
		return 1;
	}

	po->toString();	
	return 0;
}
このプログラムは、Kitty 型のポインタを Chobits 型ポインタに変換しようとしています
しかし、純粋な Kitty 型は派生クラスの情報を持たないのでキャストできません
そのため、dynamic_cast 演算子は NULL を返します


静的キャスト

動的な dynamic_cast に対して、従来の型変換
すなわち非ポリモーフィックの型変換は static_cast 演算子を用います

dynamic_cast は、実行時に型チェックを行いましたが
static_cast の場合は実行時のチェックを行わないので、変換後の型は保証されません

static_cast < type-id > ( expression )

構文は dynamic_cast と同じです
type-id には目的の型を、expression には変換する式を指定します
#include<iostream>
using namespace std;

int main() {
	double d = 3.14;
	cout << static_cast <int> (d);

	return 0;
}
このプログラムでは、double 型の変数 d を
static_cast 演算子を使って int 型に変換して出力しています


属性の削除

通常のプログラミングでは、ほとんどこのようなケースはありませんが
場合によっては変数がもつ const 属性などを破棄したい場合もあります

そのような場合、属性の上書きをすることができる特殊なキャスト演算子があります
属性の変更は const_cast を用います

const_cast < type-id > ( expression )

構文は dynamic_cast 演算子と同じです
type-id は、属性を除いて元の型と同じ型でなければいけません
このキャストで const 属性または volatile 属性を削除することができます
一般的には、const 属性の破棄を目的に使うことが多いです
#include<iostream>
using namespace std;

void Kitty(const int & cvar) {
	int *var = const_cast <int *> (&cvar);
	*var += 100;
}

int main() {
	int var = 1000;
	Kitty(var);

	cout << var;

	return 0;
}
このプログラムが出力する値は 1100 になります
Kitty() 関数では、const int で受け取っているにもかかわらず
const_cast 演算子を用いて属性を解除して変数を操作しています


ポインタ型の変換

C++では、さらにポインタのキャスト専用演算子が用意されています
この演算子は、互換性のないポインタ型のキャストやその復元をサポートします

互換性のないポインタのキャストは reinterpret_cast 演算子を用います
この演算子はポインタの、あらゆるポインタ型に変換することができます

reinterpret_cast < type-id > ( expression )

構文は dynamic_cast と同じです

この演算子は互換性のないポインタ型もキャストすることができます
そのため、確実性のない変換を行った場合プログラムの安全性に大きな影響を与えます
誤った使い方をした場合は、当然クラッシュします
#include<iostream>
using namespace std;

int main() {
	unsigned int var = 4294967295 , *po;

	char *cpo = reinterpret_cast <char *> (&var);
	po = reinterpret_cast <unsigned int *> (cpo);

	cout << "char * = " << *cpo << '\n';
	cout << "int * = " << *po << '\n';

	return 0;
}
このプログラムでは、int 型の変数のアドレスを char 型のポインタにキャストし
そのポインタ変数を再び元の unsigned int 型のポインタにキャストしています
当然、char 型のポインタの出力は意味のない記号になります

また、この演算子は整数とポインタ間の変換も行えます
#include<iostream>
using namespace std;

int main() {
	char *str = "A";
	int var = reinterpret_cast < int > (str);

	cout << var;

	return 0;
}
このプログラムでは、char * 型変数を整数に変換しています
ここで変換された整数を、再び元のポインタ型にキャストすることもできます


dynamic_cast

dynamic_cast < type-id > ( expression )

expression を type-id 型のオブジェクトに変換します
type-id は、定義済みのクラス型へのポインタまたは参照か、void へのポインタを指定します
ポインタ型にキャストできなかった場合は NULL を返します
参照にキャストできなかった場合は std::bad_cast 例外を発生させます

static_cast

static_cast < type-id > ( expression )

expression を type-id 型のオブジェクトに変換します
型チェックを行わないので、結果は保証されません

const_cast

const_cast < type-id > ( expression )

オペランド expression と type-id は同じ型である必要があります
const、volatile 属性を削除します

reinterpret_cast

reinterpret_cast < type-id > ( expression )

expression を type-id 型のポインタまたは整数に変換します
この演算子はポインタを他の任意のポインタ型に変換します
ポインタと整数の変換も行うことができます



前のページへ戻る次のページへ