RTTI概念
百度百科:通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型
MFC中RTTI源码实现
MFC是通过两个宏实现的
#define DECLARE_DYNAMIC(class_name) //声明宏
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) //实现宏
其实就是声明宏就是声明了一个CRuntimeClass的结构体对象和获取这个结构体的虚函数GetRuntimeClass
实现宏就是对这个结构体对象进行初始化和实现这个GetRuntimeClass虚函数
宏源码如下,如果你想看的更清晰的话自己随便写个类进行替换就简单了,下面的代码是我只把CRuntimeClass结构体中和RTTI关系比较重要的类写下来了
注意:如果是最上层的基类的话就是自己实现了,而不是用这两个宏(MFC已经实现过了,我说的情况是如果自己模拟MFC中的RTTI),因为CRuntimeClass结构体中的成员CRuntimeClass* m_pBaseClass是为空,而用宏的话赋值为空,则会有语法错误
struct CRuntimeClass
{
LPCSTR m_lpszClassName;//类型名
int m_nObjectSize;//对象大小
UINT m_wSchema; //版本号
CObject* (* m_pfnCreateObject)(); //动态创建类对象的函数指针
CRuntimeClass* m_pBaseClass;//基类指针
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const//检查基类表中是否有pBaseClass指向的类
{
CRuntimeClass* pBase = m_pBaseClass;
for(;pBase != NULL; pBase = pBase->m_pBaseClass)
{
if(strcmp(pBaseClass->m_lpszClassName, pBase->m_lpszClassName) == 0)
{
return TRUE;
}
}
return FALSE;
}
};
//声明宏
//##是连接作用,假如你class_name是CObject那class##class_name替换后就是classCObject
#define DECLARE_DYNAMIC(class_name) \
public: \
static const CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
//实现宏
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
//wSchema版本号上面已经默认赋值为0xffff,而pfnNew(创建对象的函数)默认为NULL
#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
const CRuntimeClass class_name::class##class_name = { \
#class_name, sizeof(class class_name), wSchema, pfnNew, \
RUNTIME_CLASS(base_class_name) }; \
CRuntimeClass* class_name::GetRuntimeClass() const \
{ return RUNTIME_CLASS(class_name); } \
#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
使用两个宏后的关系如下,所以用IsDerivedFrom就可以检查类型是否正确了,代码如下
//假如在有4个类Base Self1,Self2,Self3,而类的继承关系是Self3继承2 2继承1 1继承Base,使用两个宏的话就会如下
DECLARE_DYNAMIC(Base)
IMPLEMENT_DYNAMIC(Base,Self1)
DECLARE_DYNAMIC(Self2)
IMPLEMENT_DYNAMIC(Self1,Self2)
DECLARE_DYNAMIC(Self3)
IMPLEMENT_DYNAMIC(Self3,Self2)
这样的话就会形成Self3->Self2->Self1->Base这样一个关系
//假如上面的四个类都调用了RTTI两个宏,这样就可以用IsDerivedFrom判断Self1中是否继承了Base
Base* pObj1 = new Self3();
CRuntimeClass* pRC = pObj1->GetRuntimeClass();
BOOL bRet = pRC->IsDerivedFrom(RUNTIME_CLASS(Base));
MFC动态创建
MFC的动态创建也是提供两个宏去创建对象
#define DECLARE_DYNCREATE(class_name) //声明宏
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) //实现宏
这个宏的功能就是在上面的两个宏之间加了一个创建对象的静态函数CreateObject
#define DECLARE_DYNCREATE(class_name) \
DECLARE_DYNAMIC(class_name) \
static CObject* CreateObject();
//实现的话就是实现CreateObject这个静态函数和在初始化结构体时,给pfnNew创建对象的函数指针传了CreateObject静态函数
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
CObject* class_name::CreateObject() \
{ return new class_name; } \
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
class_name::CreateObject)