MFC运行时类型信息(RTCI)

 

RTCI(runtime class information)CObject对象提供的一个功能,它能判断一个类是否是从某个类派生而来。

 

       使用RTCI需要满足两个条件:

1、  CObject派生

2、  在类声明中添加DECLARE_DYNAMIC宏,在实现文件中添加IMPLEMENT_DYNAMIC宏。

 

 

 

示例:

// parent.h class CParent : public CObject { DECLARE_DYNAMIC(CParent); }; // parent.cpp IMPLEMENT_DYNAMIC(CParent, CObject); //derived.h class CDerived : public CObject { DECLARE_DYNAMIC(CDerived); }; // derived.cpp IMPLEMENT_DYNAMIC(CDerived, CParent); 

 用法:

CDerived* pMyClass = new CDerived; pMyClass->IsKindOf(RUNTIME_CLASS(CParent));  

 

解析:

IsKindOfCObject中的成员函数,任何从CObject派生而来的类都可以使用它,用来确定是否从特定的类派生而来。

BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const { CRuntimeClass* pClassThis = GetRuntimeClass(); // 获取当前类的CRuntimeClass指针 return pClassThis->IsDerivedFrom(pClass); }  

RUNTIME_CLASS这个宏将类名称转换为了CRuntimeClass*,它是如何做到的呢?静态库版本定义如下:

#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))

RUNTIME_CLASS(CParent)展开就是:((CRuntimeClass*)(&CParent::classCParent))

可以看出,classCParentCParent的成员变量。那它是怎么来的呢?它是DECLARE_DYNAMIC这个宏引入到类中的。

 

DECLARE_DYNAMIC宏定义如下:

#define DECLARE_DYNAMIC(class_name) / public: / static const CRuntimeClass class##class_name; / virtual CRuntimeClass* GetRuntimeClass() const; /

DECLARE_DYNAMIC宏在类中引入了一个静态常成员变量和一个用于获取当前类对象CRuntimeClass指针的虚函数。将DECLARE_DYNAMIC(CParent)展开,即为:

public: / static const CRuntimeClass classCParent; / virtual CRuntimeClass* GetRuntimeClass() const; /  

GetRuntimeClass被定义为虚函数,因为如果被定义为普通成员函数,当以一个指向派生类对象的父类指针调用GetRuntimeClass时,获得的将是对应父类的CRuntimeClass指针。这也是覆盖与多态的区别所在。

 

在类中添加的声明,对应的在实现文件中就应该有实现,IMPLEMENT_DYNAMIC宏用来完成这件事。它初始化了类的静态常变量,并且定义了GetRuntimeClass函数。宏定义如下:

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) / IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL) #define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) / const CRuntimeClass class_name::class##class_name = { / #class_name, sizeof(class class_name), wSchema, pfnNew, / RUNTIME_CLASS(base_class_name), NULL, class_init }; / CRuntimeClass* class_name::GetRuntimeClass() const / { return RUNTIME_CLASS(class_name); } /  

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; // 基类对象的CRuntimeClass指针 // Operations BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; // CRuntimeClass objects linked together in simple list CRuntimeClass* m_pNextClass; // linked list of registered classes const AFX_CLASSINIT* m_pClassInit; }; 

CRuntimeClass中有7个成员变量,还有一些成员函数。RTCI只使用了CRuntimeClass中的三个成员变量:m_lpszClassNamem_nObjectSizem_pBaseClass,也用到了IsDerivedFrom函数。

 

IsDerivedFrom通过向上遍历继承树,来判断对象是否是从某个类派生而来。

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 }  

 

你可能感兴趣的:(MFC运行时类型信息(RTCI))