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
}
posted @ 2025-12-01 23:48  矛盾空间  阅读(0)  评论(0)    收藏  举报