《深入解析MFC》这类解剖MFC内部实现的书籍中提到了MFC的RTTI(运行时类型信息)记录由DECLARE_DYNAMIC和IMPLEMENT_DYNAMIC实现。
先看看DECLARE_DYNAMIC宏的定义。如下:
#define DECLARE_DYNAMIC(class_name)
public:
static CRuntimeClass class##class_name; //声明CRuntimeClass的静态变量
virtual CRuntimeClass* GetRuntimeClass() const; //获取当前类的CRuntimeClass静态成员的指针
这里用到了一个叫CRuntimeClass的辅助结构,其简单定义如下:
struct CRuntimeClass{
//AttributeS
LPCSTR m_lpszClassName; //类名
int m_nobjectSize; //类尺寸
UINT m_wschema; //schema number of the loaded class
//object*(PASCAL *m_pfnCreateObject)();
CRuntimeClass*m_pBaseClass; //
static CRuntimeClass *pFirstClass;
CRuntimeClass *m_pNextClass;
};
再看下IMPLEMENT_DYNAMIC宏的定义,宏的名称红色标注,如下:
#define _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)\
static char _lpsz##class_name[] = #class_name; // //定义一个C类型字符串静态变量,即类的名称
//给之前在DECLARE_DYNAMIC里定义的CRuntimeClass类型的静态成员变量赋值
CRuntimeClass class_name::class##class_name = {
_lpsz##class_name, sizeof(class_name), wSchema, pfnNew,
RUNTIME_CLASS(base_class_name), NULL };
// 初始化一个名为"_init_##class_name"的AFX_CLASSINIT静态结构,同时会调用AFX_CLASSINIT的构造函数
static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); //括号部分是初始化列表
CRuntimeClass* class_name::GetRuntimeClass() const
{return &class_name::class##class_name; }
#define IMPLEMENT_DYNAMIC(class_name,base_class_name)\
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0XFFFF, NULL)
而RUNTIME_CLASS宏定义如下:
//从某个指定的class直接得到它的CRuntimeclass静态成员
#define RUNTIME_CLASS(class_name)
(&class_name::class##class_name)
AFX_CLASSINIT的定义如下:
//注意它是一个struct结构,拥有一个构造函数
struct AFX_CLASSINIT {
AFX_CLASSINIT(CRuntimeClass *pNewClass);
};
//作用是给指定的class_name的class##class_name静态变量的最后一个成员m_pNextClass赋值
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass *pNewClass)
{
//类成员classCRuntimeClass成员的pNext指向CRuntimeClass::pFirstClasse;然后 //CRuntimeClass::pFirstClasse这个指针又指向了classCRuntimeClass这个类成员对象
pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
//让m_pNextClass指向pFirstClass所指的CRuntimeClass变量
CRuntimeClass::pFirstClass = pNewClass;
//让pFirstClass指向pNewClass所指的变量,也就是本class的CRuntimeClass静态变量
}
在《深入浅出MFC》侯捷译一书中,作者利用控制台程序仿真实现MFC的RTTI部分
以MFC的CObject,CCmdTarget,CWinThread,CWinApp,CMyWinApp等大类为例,提取运行
类别信息,并建立了一张类别型录的链表,如下图所示:
以DECLARE_DYNAMIC(CCmdTarget)为例展开:
public:
static CRuntimeClass classCCmdTarget;
virtual CRuntimeClass* GetRuntimeClass() const;
以MPLEMENT_DYNAMIC(CCmdTarget,CObject)展开
static char _lpszCCmdTarget[] = "CCmdTarget";
CRuntimeClass CCmdTarget::classCCmdTarget = { _lpszCCmdTarget, sizeof(CCmdTarget), 0XFFFF, NULL,
(&CCmdTarget::classCCmdTarget), NULL };
static AFX_CLASSINIT _init_CCmdTarget(&CCmdTarget::classCCmdTarget);
CRuntimeClass* CCmdTarget::GetRuntimeClass() const
{
return &CCmdTarget::classCCmdTarget;
}