C++ プログラミングガイド

第 6 章 実行時の型識別

本章では、実行時の型識別 (RTTI) の使用について説明します。この機能は、コンパイル時には確認できない型情報を、プログラムの実行時に調べる場合に使用してください。

静的な型と動的な型

C++ では、クラスへのポインタには、ポインタ宣言の中に書かれた型である「静的な型」と、参照された実際の型によって決定される「動的な型」があります。オブジェクトの動的な型は、静的な型から派生したものであればいずれのクラス型でもかまいません。

次の例で、ap には静的な型 A* と動的な型 B* があります。


class A {};
class B: public A {};
extern B bv;
extern A* ap = &bv;

RTTI によって、プログラマがポインタの動的な型を決定できるようになります。

RTTI オプション

C++ 5.0 の互換モード (-compat=4) で RTTI を行うには、実装のためにかなりの資源が必要になります。このモードでは、デフォルトで RTTI は無効になっています。RTTI 実装を有効にし、かつ関連する typeid キーワードの認識を有効にするには、 -features=rtti オプションを使用してください。RTTI 実装を無効にし、かつ関連する typeid キーワードの認識を無効にするには、-features=no%rtti オプション (デフォルト) を使用してください。

C++ 5.0 の標準モード (デフォルトモード) の場合、RTTI がプログラムのコンパイルや実行に大きな影響を与えることはありません。標準モードでは、RTTI は常に有効になります。

typeid 演算子

typeid 演算子はクラス type_info のオブジェクトへの参照を生成します。これはそのオブジェクトの最も派生の進んだ型を記述するものです。typeid() 関数を使用するためには、ソースコードが <typeinfo> ヘッダーファイルをインクルード (#include) していなければなりません。この演算子とクラスの組み合わせは、比較を行うときにその利点を発揮します。そのような比較では、次の例に示すように最上位の constvolatile 修飾子は無視されます。この例では、AB はデフォルトのコンストラクタを持つ型です。


#include <typeinfo>
#include <assert.h>
void use_of_typeinfo( )
{
      A a1;
      const A a2;
      assert( typeid(a1) == typeid(a2) );
      assert( typeid(A)  == typeid(const A) );
      assert( typeid(A)  == typeid(a2) );
      assert( typeid(A)  == typeid(const A&) );
      B b1;
      assert( typeid(a1) != typeid(b1) );
      assert( typeid(A)  != typeid(B) ); 
}

typeid 演算子はヌルポインタが与えられたとき bad_typeid 例外割り込みを生成します。

type_info クラス

クラス type_info は typeid 演算子によって生成された型情報を記述します。 type_info によって提供される基本関数は等式、不等式、before、および name です。<typeinfo.h> 中の定義は次のようになります。


    class type_info {
        public:
            virtual ‾type_info( );
            bool operator==( const type_info &rhs ) const;
            bool operator!=( const type_info &rhs ) const;
            bool before( const type_info &rhs ) const;
            const char *name( ) const;
        private:
            type_info( const type_info &rhs );
            type_info &operator=( const type_info &rhs );
    };

before 関数は、2 つの型の実装時の照合順序を比較します。name 関数は、変換と表示に適した実装定義のヌルで終わる多バイト文字列を返します。

コンストラクタは非公開メンバー関数なので、プログラマが型“type_info”の変数を作成することはできません。“type_info”オブジェクトを得るには“typeid”演算子を使用してください。