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链表。这一点和侯捷先生所述有点不同。

你可能感兴趣的:(CRuntimeClass的作用详解)