MFC RTTI 解析
在 C++ 标准 RTTI(dynamic_cast / typeid)普及之前,MFC就通过 DECLARE_DYNAMIC,IMPLEMENT_DYNAMIC 等宏实现了一套 RTTI。
CRuntimeClass 是核心部分,用于描述每个 class 信息。每个继承 CObject 的 class 和一个 CRuntimeClass 的结构体对应。
struct CRuntimeClass
{
// Attributes
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema; // schema number of the loaded class
CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
CRuntimeClass* m_pBaseClass;
// Operations
CObject* CreateObject();
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;
...
// CRuntimeClass objects linked together in simple list
CRuntimeClass* m_pNextClass; // linked list of registered classes
};
DECLARE_DYNAMIC 在 class 里面注入一个静态成员和虚函数
#define DECLARE_DYNAMIC(class_name) \
public: \
static const AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
RUNTIME_CLASS 返回某个类所对应的 CRuntimeClass
#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
IMPLEMENT_RUNTIMECLASS 初始化静态成员并实现虚函数
#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
AFX_COMDAT const 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); } \
MFC 提供了一个更简单的宏 IMPLEMENT_DYNAMIC
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
举例
// 展开前
class Foo : CObject
{
DECLARE_DYNAMIC(Foo);
};
IMPLEMENT_DYNAMIC(Foo, CObject);
// 展开后
class Foo : CObject
{
public:
static const CRuntimeClass classFoo;
virtual CRuntimeClass* GetRuntimeClass() const;
};
CRuntimeClass class_name::classFoo =
{
"Foo",
sizeof(class Foo),
0xFFFF,
NULL,
(CRuntimeClass*)&CObject::classCObject,
NULL
};
CRuntimeClass* class_name::GetRuntimeClass() const
{
return (CRuntimeClass*)&Foo::classFoo;
}
IsKindOf 是最常用的类型判断方法。每个 class 的 IsKindOf 方法都调用了 CRuntimeClass::IsDerivedFrom
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
...
// simple SI case
CRuntimeClass* pClassThis = GetRuntimeClass();
return pClassThis->IsDerivedFrom(pClass);
}
IsDerivedFrom 通过成员 m_pBaseClass 不断向基类遍历,判断继承关系,这样就实现了运行时类型识别
BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const
{
...
// simple SI case
const CRuntimeClass* pClassThis = this;
while (pClassThis != NULL)
{
if (pClassThis == pBaseClass)
return TRUE;
pClassThis = pClassThis->m_pBaseClass;
}
return FALSE; // walked to the top, no match
}

浙公网安备 33010602011771号