実行時型情報
オブジェクトの型を知る
C++のようなオブジェクト指向言語では、ポリモーフィズムをサポートしています
オーバーライドで知ったように、場合のよっては実行されるまで性質がわからないオブジェクトが存在します
この柔軟性はプログラムの効率に非常に大きな影響を与えます
しかし、実行中に現在のオブジェクトの型を知る必要があるケースもあります
といって、コンパイル時にオーバーライドされた仮想関数の型を知ることはできません
そこで実行時型情報という機能を用いて、実行中にその型を調べる必要があります
実行時型情報は RTTI(Run-Time Type Identification) とも呼ばれます
この機能を用いることで、ポリモーフィッククラスの型の操作などが動的に行えます
実行時型情報を得るには typeid 演算子 を用います
この演算子は const type_info & を返します
type_info クラスを使用するには <typeinfo> ヘッダをインクルードします
typeid(object)
object には、調べる型を指定します
これによって、object の型情報を含む type_info オブジェクトの参照が返ります
type_info クラスは、いくつかの便利な公開メンバがあります
まず、オブジェクトの名前を得るには name() メンバ関数を使います
const char * type_info::name()
この関数は、type_info がもつ型の名前を返します
#include<iostream>
#include<typeinfo>
using namespace std;
class Kitty {
public:
virtual void func() {} ;
} obj1;
class Chobits : public Kitty {
public:
void func() {}
} obj2 ;
int main() {
Kitty *po = &obj1;
cout << "Class type = " << typeid (*po).name() << '\n';
po = &obj2;
cout << "Class type = " << typeid (*po).name() << '\n';
return 0;
}
結果は次のように出力されます
Class type = Kitty
Class type = Chobits
typeid() は、ポリモフィッククラスの場合
実行時にポインタが指すオブジェクト方を判別します
当然、非ポリモフィッククラスの場合は基本型になります
この機能は、何も仮想関数を持つクラス以外にも使えます
もちろん、コンパイル時に型が判明しているのなら、調べることに意味はありませんが
また、type_info クラスは、等価演算子 == , != をオーバーロードしています
これで、オブジェクトの型を比較することができます
bool type_info::operator == (const type_info &);
bool type_info::operator != (const type_info &);
これを利用すれば、フロー制御に用いることが容易です
演算子は良そうどおりの動作で、== は双方のオペランドが等しければ
!= は、等しくなければ true を、そうでなければ false を返します
#include<iostream>
#include<typeinfo>
#include<stdlib.h>
using namespace std;
class Kitty {
public:
virtual void func() {} ;
} obj1;
class Chobits : public Kitty {
public:
void func() {}
} obj2 ;
int main() {
Kitty *po;
srand((unsigned)time( NULL ));
if (rand() % 2) po = &obj1;
else po = &obj2;
if (typeid (obj1) == typeid (*po)) cout << "Kitty on your lap\n";
else cout << "Chobits\n";
return 0;
}
このプログラムは、Kitty 基本クラスと、それを継承しているChobits 派生クラスがあり
これらのクラスはポリモーフィッククラスで、最初にいずれかのオブジェクトが
ランダムで Kitty * 型のポインタ変数にアドレスを代入します
Kitty 型ポインタ変数 po は、どのオブジェクトを指しているのかわかりません
そこで、typeid() で type_info の参照を得て、それを比較して確認しています
このように、コンパイル時に決定されないオブジェクト型の判定にRTTIの機能を発揮させることができます
また、typeid 演算子にはもう一つの書式があります
typeid は変数ではなく、型名を指定することもできます
typeid ( type-name );
type-name には、型の名前を直接指定します
この場合は、指定した型の type_info オブジェクトを取得します
この構文は、一般的に型を比較する時に用います
#include<iostream>
using namespace std;
class Kitty {};
int main() {
Kitty obj;
if (typeid ( Kitty ) == typeid (obj))
cout << "Kitty on your lap";
return 0;
}
このプログラムでは、オブジェクトの比較のために typeid(Kitty) と指定しています
このように、オブジェクトの型の比較にはこの構文を用いることができます
typeid
typeid( type-id )
typeid( expression )
特定の型を表す type_info への参照を返します
この演算子が返すものは const type_info & です
type-id - 型を指定します
expression - 調べるオブジェクトの式を指定します