ランタイム クラス情報へのアクセス方法

更新 : 2007 年 11 月

ここでは、実行時にオブジェクトのクラス情報にアクセスする方法について説明します。

t91eb9y9.alert_note(ja-jp,VS.90).gifメモ :

MFC は、Visual C++ 4.0 で導入されたランタイム型情報 (RTTI) のサポートを使用しません。

CObject からの派生クラスで、「CObject からのクラスの派生」で説明されている DECLARE_DYNAMICIMPLEMENT_DYNAMICDECLARE_DYNCREATEIMPLEMENT_DYNCREATE、または DECLARE_SERIALIMPLEMENT_SERIAL のいずれかのマクロの組み合わせを宣言すると、実行時に CObject クラスでオブジェクトのクラスを正確に判定できます。

実行時にオブジェクトのクラスを判定できると、関数の引数の特別な型チェックが必要な場合、およびオブジェクトのクラスに依存する専用のプログラムを記述する場合に特に便利です。ただし、この技法は通常お勧めしません。仮想関数の機能が重複するからです。

CObject のメンバ関数 IsKindOf では、あるオブジェクトが特定のクラスのオブジェクトであるか、その派生クラスのオブジェクトであるかを判定できます。IsKindOf では、引数として CRuntimeClass オブジェクトを使用します。これは、RUNTIME_CLASS マクロでクラス名を指定して取得できます。

RUNTIME_CLASS マクロを使用するには

  • RUNTIME_CLASS でクラス名 (次の例では CObject) を指定します。

    CRuntimeClass* pClass = RUNTIME_CLASS( CObject );   
    

ランタイム クラスのオブジェクトに直接アクセスする必要はほとんどありません。通常は、次の例に示すように、ランタイム クラスのオブジェクトを関数 IsKindOf の引数として渡します。IsKindOf 関数は、オブジェクトが特定のクラスに属しているかどうかを調べます。

関数 IsKindOf を使用するには

  1. 対象となるクラスがランタイム クラスをサポートしていることを確認します。つまり、このクラスが CObject から直接または間接的に派生しており、「CObject からのクラスの派生」で説明したように、DECLARE_DYNAMICIMPLEMENT_DYNAMICDECLARE_DYNCREATEIMPLEMENT_DYNCREATE、または DECLARE_SERIALIMPLEMENT_SERIAL のいずれかのマクロの組み合わせを宣言している必要があります。

  2. 対象となるクラスのオブジェクトに対してメンバ関数 IsKindOf を呼び出します。このメンバ関数の CRuntimeClass 型引数は、次の例のように RUNTIME_CLASS マクロによって生成されます。

    class CPerson : public CObject 
    {
       DECLARE_DYNAMIC( CPerson )
    
       // other declarations
    };
    
    IMPLEMENT_DYNAMIC( CPerson, CObject )
    
    IMPLEMENT_DYNCREATE(CMyDynCreateObj, CObject)
    
    void MemoryCorruptingSnippet(bool bCorrupt)
    {
       if (bCorrupt)
       {
          CAge* pcage = new CAge(21);  // CAge is derived from CObject.
          Age* page = new Age(22);     // Age is NOT derived from CObject.
          *(((char*)pcage) - 1) = 99;   // Corrupt preceding guard byte
          *(((char*)page) - 1) = 99;    // Corrupt preceding guard byte
          AfxCheckMemory();
       }
    }
    
    void SomeFunction(void)
    {
       CObject* pMyObject = new CPerson;
    
       if(NULL != pMyObject &&
         pMyObject->IsKindOf( RUNTIME_CLASS( CPerson ) ) )
       {
          //if IsKindOf is true, then cast is all right
          CPerson* pmyPerson = (CPerson*) pMyObject ;
          pmyPerson->AssertValid();
          // other code goes here...
       }
    
       delete pMyObject;
    }
    
    t91eb9y9.alert_note(ja-jp,VS.90).gifメモ :

    オブジェクトが指定したクラスまたはその派生クラスのメンバである場合、IsKindOf は TRUE を返します。IsKindOf は多重継承および仮想基本クラスをサポートしません。ただし、必要に応じて、MFC の派生クラスで多重継承を使用できます。

ランタイム クラス情報は、オブジェクトの動的生成でも使われます。この方法については、「オブジェクトの動的生成」を参照してください。

シリアル化とランタイム クラス情報の詳細については、「MFC のファイル」、および「シリアル化」を参照してください。

参照

概念

CObject の使い方