CRuntimeClass的作用詳解

// Runtime class serialization code

CRuntimeClass* PASCALCRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)

         //loads a runtime class description

{

         WORDnLen;//類名的長度

         charszClassName[64];//存放類名的字符數組

         CRuntimeClass*pClass;

 

         WORDwTemp;

         ar>> wTemp; *pwSchemaNum = wTemp;//加載版本號

         ar>> nLen;//加載類名長度

 

         if(nLen >= _countof(szClassName) ||

                   ar.Read(szClassName,nLen*sizeof(char)) != nLen*sizeof(char))//讀取類名到數組

         {

                   returnNULL;

         }

         szClassName[nLen]= '\0';//字符串末尾補零

 

         //search app specific classes

         AFX_MODULE_STATE*pModuleState = AfxGetModuleState();//獲取模塊狀態

         AfxLockGlobals(CRIT_RUNTIMECLASSLIST);//進入關鍵代碼段以訪問全局變量

         for(pClass = pModuleState->m_classList; pClass != NULL;

                   pClass= pClass->m_pNextClass)

         {

                   if(lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)//在類別型錄網裏面找到

                   {

                            AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

                            returnpClass;

                   }

         }

         AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

 

         TRACE1("Warning:Cannot load %hs from archive.  Class notdefined.\n",

                   szClassName);

 

         returnNULL; // not found

}

 

注意:m_classList定義在類AFX_MODULE_STATE中

CTypedSimpleList<CRuntimeClass*>m_classList;  它是類別型錄網鏈表的表頭

struct CRuntimeClass

{

// Attributes

         LPCSTRm_lpszClassName;

         intm_nObjectSize;

         UINTm_wSchema; // schema number of the loaded class

         CObject*(PASCAL* m_pfnCreateObject)(); // NULL => abstract class

         CRuntimeClass*m_pBaseClass;

 

// Operations

         CObject*CreateObject();

         BOOLIsDerivedFrom(const CRuntimeClass* pBaseClass) const;

 

// Implementation

         voidStore(CArchive& ar) const;

         staticCRuntimeClass* PASCAL Load(CArchive& ar,UINT* pwSchemaNum);

 

         //CRuntimeClass objects linked together in simple list用簡單鏈錶鏈接起來

         CRuntimeClass*m_pNextClass;       // linked list ofregistered classes

};

 

void CRuntimeClass::Store(CArchive& ar)const

         //stores a runtime class description

{

         WORDnLen = (WORD)lstrlenA(m_lpszClassName);//得到類名的長度

         ar<< (WORD)m_wSchema << nLen;//存檔版本號和類名長度

         ar.Write(m_lpszClassName,nLen*sizeof(char));//寫入類名

}

 

總結:CRuntimeClass::Load函數首先加載版本號和類名長度,然後再利用加載的類名長度去加載出類名,利用此類名去檢索類別型錄網看其有否記錄在案。

     CRuntimeClass::Store只是簡單地依次存儲版本號、類名長度、類名到歸檔中。

 

#defineDECLARE_DYNAMIC(class_name) \

public: \

         staticconst AFX_DATA CRuntimeClass class##class_name; \

         virtualCRuntimeClass* GetRuntimeClass() const; \

 

// not serializable, but dynamicallyconstructable

#defineDECLARE_DYNCREATE(class_name) \

         DECLARE_DYNAMIC(class_name)\

         staticCObject* PASCAL CreateObject();

 

#define DECLARE_SERIAL(class_name) \

         _DECLARE_DYNCREATE(class_name)\

         AFX_APIfriend CArchive& AFXAPI operator>>(CArchive& ar, class_name*&pOb);

 

// generate static object constructor forclass registration

void AFXAPI AfxClassInit(CRuntimeClass*pNewClass);

struct AFX_CLASSINIT

         {AFX_CLASSINIT(CRuntimeClass* pNewClass) { AfxClassInit(pNewClass); } };

struct AFX_CLASSINIT_COMPAT

         {AFX_CLASSINIT_COMPAT(CRuntimeClass* pNewClass); };

 

#define IMPLEMENT_RUNTIMECLASS(class_name,base_class_name, wSchema, pfnNew) \

         AFX_COMDATconst AFX_DATADEF CRuntimeClass class_name::class##class_name = { \

                   #class_name,sizeof(class class_name), wSchema, pfnNew, \

                            RUNTIME_CLASS(base_class_name),NULL }; \

         CRuntimeClass*class_name::GetRuntimeClass() const \

                   {return RUNTIME_CLASS(class_name); } \

 

#define IMPLEMENT_DYNAMIC(class_name,base_class_name) \

         IMPLEMENT_RUNTIMECLASS(class_name, base_class_name,0xFFFF, NULL)

 

#define IMPLEMENT_DYNCREATE(class_name,base_class_name) \

         CObject*PASCAL class_name::CreateObject() \

                   {return new class_name; } \

         IMPLEMENT_RUNTIMECLASS(class_name, base_class_name,0xFFFF, \

                   class_name::CreateObject)

 

#define IMPLEMENT_SERIAL(class_name,base_class_name, wSchema) \

         CObject*PASCAL class_name::CreateObject() \

                   {return new class_name; } \

         _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name,wSchema, \

                   class_name::CreateObject)\

         AFX_CLASSINIT_init_##class_name(RUNTIME_CLASS(class_name)); \

         CArchive&AFXAPI operator>>(CArchive& ar, class_name* &pOb) \

                   {pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \

                            returnar; } \

 

// optional bit for schema number thatenables object versioning

#define VERSIONABLE_SCHEMA  (0x80000000)

 

BOOL CRuntimeClass::IsDerivedFrom(constCRuntimeClass* pBaseClass) const

{

         ASSERT(this!= NULL);

         ASSERT(AfxIsValidAddress(this,sizeof(CRuntimeClass), FALSE));

         ASSERT(pBaseClass!= NULL);

         ASSERT(AfxIsValidAddress(pBaseClass,sizeof(CRuntimeClass), FALSE));

 

         //simple SI case

         constCRuntimeClass* pClassThis = this;

         while(pClassThis != NULL)

         {

                   if(pClassThis == pBaseClass)

                            returnTRUE;

#ifdef _AFXDLL

                   pClassThis= (*pClassThis->m_pfnGetBaseClass)();

#else

                   pClassThis= pClassThis->m_pBaseClass;//不斷往基類上溯

#endif

         }

         returnFALSE;       // walked to the top, nomatch

}

 

void AFXAPI AfxClassInit(CRuntimeClass*pNewClass)

{

         AFX_MODULE_STATE*pModuleState = AfxGetModuleState();

         AfxLockGlobals(CRIT_RUNTIMECLASSLIST);//進入關鍵代碼段

         pModuleState->m_classList.AddHead(pNewClass);//將新結點加到表頭後面

         AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

}

 

// generate static object constructor forclass registration

//爲類的註冊產生一個靜態的對象構造函數

void AFXAPI AfxClassInit(CRuntimeClass*pNewClass);

struct AFX_CLASSINIT

         {AFX_CLASSINIT(CRuntimeClass* pNewClass) { AfxClassInit(pNewClass); } };

 

 

由上面所述可知動態識別和動態創建都沒產生RuntimeClas鏈表(沒有用next指針連起來),而只有與父類的鏈表(用m_pBaseClass連起來)。只有序列化時,纔有CRuntimeClass鏈表。這一點和侯捷先生所述有點不同。

發佈了3 篇原創文章 · 獲贊 29 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章