簡介:
CRuntimeClass是MFC實現的RTTI(運行時類型信息),MFC中的很多類需要由框架動態創建(比如文檔、視圖、框架視窗類等等),所以從CObject繼承的類如果需要這種能力,必須實現它的CRuntimeClass,包括CreateObject靜態方法(這個方法簡單調用new CMyClass)。而做到這個很簡單,使用DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏就自動擁有這個特性,看看這兩個宏的定義就能理解其原理。
CRuntimeClass在MFC中定義為一個數據結構,在檔案AFX.H中聲明,它是用來串起MFC從COBJECT繼承下來的所有類(相當於一根繩,只要你牽住繩的一頭你就可以得到繩上的所有數據),你也可以把你自己寫的類加入這根繩。
每個從CObject中派生的類都有一個CRuntimeClass對象同它關聯以完成在運行時得到類實例的信息或者是它的基類。
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結構,你必須在你想要獲取運行時對象信息的類的實現中包括IMPLEMENT_DYNAMIC,IMPLEMENT_DYNCREATE,或IMPLEMENT_SERIAL宏。
請參閱:
CObject::GetRuntimeClass, CObject::IsKindOf, RUNTIME_CLASS, IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, IMPLEMENT_SERIALCRuntimeClass在MFC中的作用很重要,因為MFC利用它來進行類的動態確定,即是通過
類變數來判定該變數是否為某一類的實例。由於
指針的類型是可以轉換的,所以時常會出現從A到B的轉換導致錯誤。而在MFC的各種書籍中對CRuntimeClass的介紹是比較少的,在這裡總結它的一些用法。
動態確定類
在MFC中CObject::IsKindOf( const CRuntimeClass* pClass ) 利用CRuntimeClass來進行判定,如果你生成的類是以CObject為基礎的,你可以使用該成員函式來判定。下面舉一個例子來加深了解。
class CAge : public CObjectBOOL 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,避免強制轉換帶來的錯誤}
生成類
CObject CRuntimeClass::CreateObject(void)可以產生一個
類變數。作用和new類似,但在某些特殊場合有獨特的作用。下面舉一個例子來加深了解。
假定有以下幾個類定義
class CWndA: public CWndclass CWndB: public CWndfunction1(){ CRuntimeClass* pC=RUNTIME_CLASS( CWndA ); CreateWnd(pC);}CWnd* CreateWnd(CRuntimeClass* pClass){ return (CWnd*)pClass->CreateObject();}
在上面例子中,CreateWnd返回的是CWnd* 其實它是一個CWndA*。你可以進行由子類到父類的強制轉換而不必要擔心出錯。使用CRuntimeClass可以代替使用switch生產類實例的一些繁瑣。(請好好想想它的用途,當你發現它的好處時,你一定會大吃一驚,M$使用宏來實現類的動態檢測,如果誰有興趣可以去看看MFC的原始碼。)
注意:在類的定義中使用IMPLEMENT_DYNCREATE後方可生效。