MFC程序设计(七)运行时类信息机制
运行时类信息机制的作用
我们在创建对象时,自己是清楚对象属于哪个类,但是计算机却不清楚。而MFC运行时类信息机制就是解决这个问题而存在的
运行时类信息机制的使用
我们在创建一个类时,只有满足以上三个条件,该类才能支持运行时类信息机制
代码验证
#include<afxwin.h>
#include<iostream>
class CAnimal : public CObject
{
DECLARE_DYNAMIC(CAnimal);
};
IMPLEMENT_DYNAMIC(CAnimal, CObject)
class CDog : public CAnimal
{
DECLARE_DYNAMIC(CDog);
};
IMPLEMENT_DYNAMIC(CDog, CAnimal)
int main()
{
CDog yellowdog;
if (yellowdog.IsKindOf(RUNTIME_CLASS(CDog)))
{
std::cout << "yellowdog is CDog" << std::endl;
}
else
{
std::cout << "yellowdog is not CDog" << std::endl;
}
return 0;
}
程序运行,我们发现计算机判断结果是对象yellowdog属于CDog类。
代码修改为判断yellowdog是否属于CAnimal类时,计算机判断结果是对象yellowdog也属于CAnimal类
代码修改为判断yellowdog是否属于CWnd类时,计算机判断结果是对象yellowdog不属于CWnd类
而计算机判断对象是否属于某个类,依据就是上文的三个条件
运行时类信息机制的解析
宏展开
接下来我们展开上文中CDog中实现运行时类信息机制的两个宏,观察该机制是如何工作的
//DECLARE_DYNAMIC(CDog)宏展开
public:
static const CRuntimeClass classCDog; //静态的结构体
virtual CRuntimeClass* GetRuntimeClass() const; //虚函数
//IMPLEMENT_DYNAMIC(CDog,CAnimal)宏展开
IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL, NULL)
//IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL, NULL)宏展开
AFX_COMDAT const CRuntimeClass CDog::classCDog =
{
"CDog", //类名称
sizeof(class CDog), //类大小
0xFFFF, //类版本 0xFFFF
NULL, //动态创建机制使用,这里为NULL
//RUNTIME_CLASS(CAnimal), 这也是一个宏,如下是宏展开的样子
((CRuntimeClass*)(&CAnimal:classCAnimal)), //返回父类静态结构体的地址
NULL,//不使用为NULL
NULL //不使用为NULL
};
CRuntimeClass* CDog::GetRuntimeClass() const
{
//return RUNTIME_CLASS(CDog); 这也是一个宏,如下是宏展开的样子
return ((CRuntimeClass*)(&CDog::classCDog));//返回头节点
}
struct CRuntimeClass//CRuntimeClass结构体信息如下所示
{
LPCSTR m_lpszClassName;//类名称
int m_nObjectSize;//类大小
UINT m_wSchema; //类版本
CObject* (PASCAL* m_pfnCreateObject)(); //动态创建才会使用 暂时NULL函数指针
CRuntimeClass* m_pBaseClass;//父类信息
CRuntimeClass* m_pNextClass; //NULL
const AFX_CLASSINIT* m_pClassInit;//NULL
}
宏展开各部分作用
如下是IMPLEMENT_DYNAMIC()展开后样子
如图所示,子类指向父类,这又是一个链表
执行过程
通过遍历上图所示的链表来检查类对象属于哪个类
接下来我们以yellowdog.IsKindOf(RUNTIME_CLASS(CDog))为例讲解整个执行过程
yellowdog.IsKindOf(RUNTIME_CLASS(CDog))//函数内部this为&yellowdog,参数为链表头
{
CRuntimeClass* pClassThis = GetRuntimeClass();//利用&yellowdog调用宏展开的虚函数,获取链表头结点classCDog
return pClassThis->IsDerivedFrom(RUNTIME_CLASS(CDog))//函数内部this和参数都是链表头classCDog
{
const CRuntimeClass* pClassThis = this;//获取链表头classCDog
while (pClassThis != NULL)
{
if (pClassThis == RUNTIME_CLASS(CDog))
return TRUE;
pClassThis = pClassThis->m_pBaseClass;
}
return FALSE;
}
}
原文地址:https://blog.csdn.net/2301_78838647/article/details/145430317
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!