複製鏈接
請複製以下鏈接發送給好友

CRuntimeClass

鎖定
CRuntimeClass沒有基類。 每個由CObject派生的類都與一個CRuntimeClass結構相聯繫,用户可以使用該結構獲取一個對象及其基類的運行時信息。當需要額外的函數參數檢查時,或當用户必須根據一個對象的類編寫特殊目的代碼時,在運行時確定該對象的類就非常有用。C++並不直接支持運行時類的信息。
中文名
CRuntimeClass
特    點
沒有基類
相    關
與一個CRuntimeClass結構相聯繫
功    能
獲取對象及其基類的運行時信息

CRuntimeClass簡介

CRuntimeClass是MFC實現的RTTI(運行時類型信息),MFC中的很多類需要由框架動態創建(比如文檔、視圖、框架窗口類等等),所以從CObject繼承的類如果需要這種能力,必須實現它的CRuntimeClass,包括CreateObject靜態方法(這個方法簡單調用new CMyClass)。而做到這個很簡單,使用DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏就自動擁有這個特性,看看這兩個宏的定義就能理解其原理。
CRuntimeClass在MFC中定義為一個數據結構,在文件AFX.H中聲明,它是用來串起MFC從COBJECT繼承下來的所有類(相當於一根繩,只要你牽住繩的一頭你就可以得到繩上的所有數據),你也可以把你自己寫的類加入這根繩。
每個從CObject中派生的類都有一個CRuntimeClass對象同它關聯以完成在運行時得到類實例的信息或者是它的基類。 [1] 

CRuntimeClass信息概述

此結構具有下列成員:
LPCSTR m_lpszClassName 
    存放ASCII類名的以空字符結尾的字符串。
int m_nObjectSize
    以字節為單位給出對象的大小。若此對象具有指向被分配的內存的數據成員,則此值不包含該內存的大小。
UINT m_wSchema
    分類編號(對不可分類的類,該值為-1)。對於此分類編號的詳細説明,參見IMPLEMENT_SERIAL宏。
CObject* ( PASCAL* m_pfnCreateObject )
    是一個指向缺省的構造函數的函數指針,該構造函數創建一個你的類的對象(只有在類支持動態創建時才有
    效;否則,返回NULL)。
CRuntimeClass* ( PASCAL* m_pfn_GetBaseClass )( )
    如果你的應用程序是動態地鏈接到MFC的AFXDLL版本,則是一個指向函數的指針,該函數返回基類的
    CRuntimeClass結構。
CRuntimeClass* m_pBaseClass
    如果你的應用程序是靜態地鏈接到MFC的,則是一個指向基類的CRuntimeClass結構的指針。
Feature Only in Professional and Enterprise Editions 
    只有在Visual C++的專業版和企業版中才支持對MFC的靜態鏈接。
CObject* CreateObject( );
    從CObject派生的類可以支持動態創建,這是在運行時創建一個指定類的對象的能力。例如,文檔,視圖和
    框架類就應該支持動態創建。CreateObject成員函數可以用來實現這個功能,在運行時為這些類創建對象。
BOOL IsDerivedFrom( const CRuntimeClass* pBaseClass) const;
    如果IsDerivedFrom類成員的類是從基類派生而來,該基類的CRuntimeClass結構作為一個參數給出,則返
    回 TRUE。IsDerivedFrom從該成員的類開始向上沿派生類鏈經過所有的類直到頂端,並且只有在沒有與
    基類匹配 的類時才返回FALSE。

CRuntimeClass注意

要使用CRuntimeClass結構,你必須在你想要獲取運行時對象信息的類的實現中包括IMPLEMENT_DYNAMIC,IMPLEMENT_DYNCREATE,或IMPLEMENT_SERIAL宏。
請參閲:
CObject::GetRuntimeClass, CObject::IsKindOf, RUNTIME_CLASS, IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, IMPLEMENT_SERIALCRuntimeClass在MFC中的作用很重要,因為MFC利用它來進行類的動態確定,即是通過類變量來判定該變量是否為某一類的實例。由於指針的類型是可以轉換的,所以時常會出現從A到B的轉換導致錯誤。而在MFC的各種書籍中對CRuntimeClass的介紹是比較少的,在這裏總結它的一些用法。

CRuntimeClass動態確定類

在MFC中CObject::IsKindOf( const CRuntimeClass* pClass ) 利用CRuntimeClass來進行判定,如果你生成的類是以CObject為基礎的,你可以使用該成員函數來判定。下面舉一個例子來加深瞭解。
class CAge : public CObject
BOOL IsAge(CObject* pO)
{
    return pO->IsKindOf( RUNTIME_CLASS( CAge ) );
}
    BOOL IsAge2(CAge* pO)
{
    return pO->IsKindOf( RUNTIME_CLASS( CAge ) );
}

void main(void)
{
    CObject a;
    CAge b;
    IsAge(&a);//return FALSE
    IsAge(&b);//return TRUE
    IsAge2((CAge*)&a);//return FALSE,避免強制轉換帶來的錯誤
}

CRuntimeClass生成類

CObject CRuntimeClass::CreateObject(void)可以產生一個類變量。作用和new類似,但在某些特殊場合有獨特的作用。下面舉一個例子來加深瞭解。
假定有以下幾個類定義
class CWndA: public CWnd
class CWndB: public CWnd

function1()
{ 
    CRuntimeClass* pC=RUNTIME_CLASS( CWndA );
    CreateWnd(pC);
}

CWnd* CreateWnd(CRuntimeClass* pClass)
{
    return (CWnd*)pClass->CreateObject();
}
在上面例子中,CreateWnd返回的是CWnd* 其實它是一個CWndA*。你可以進行由子類到父類的強制轉換而不必要擔心出錯。使用CRuntimeClass可以代替使用switch生產類實例的一些繁瑣。(請好好想想它的用途,當你發現它的好處時,你一定會大吃一驚,M$使用宏來實現類的動態檢測,如果誰有興趣可以去看看MFC的源代碼。)
注意:在類的定義中使用IMPLEMENT_DYNCREATE後方可生效。
參考資料