MFC 运行时类信息机制
2023-12-25 06:28:50
目录
运行时类信息机制概述
在程序运行过程中可以获知对象的类的相关信息(例如∶对象是否属于某个类)
如何使用?
- 类必须派生自CObject
- 类内必须添加声明宏DECLARE_DYNAMIC( theClass )
- 类外必须添加实现宏IMPLEMENT_DYNAMIC(theClass , baseClass)
?
当一个类具备上述三个要件后,CObject : : IsKindOf函数就可以正确判断对象是否属于某个类。
测试
创建一个控制台项目,使用MFC静态库
#include <afxwin.h>
#include <iostream>
using namespace std;
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(CWnd))) {
cout << "yellowdog is CWnd" << endl;
}
else {
cout << "yellowdog isnot CWnd" << endl;
}
return 0;
}
宏代换分析
DECLARE_DYNAMIC( CDog )
代换为
第一个是结构体,第二个是一个虚函数,用来获取本类的结构体的地址
public:
static const CRuntimeClass classCDog;
virtual CRuntimeClass* GetRuntimeClass() const;
IMPLEMENT_DYNAMIC( CDog, CAnimal )
代换为
IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL, NULL)
代换为
AFX_COMDAT const CRuntimeClass CDog::classCDog = {
"CDog",
sizeof(class CDog),
0xFFFF,
NULL,
// RUNTIME_CLASS(CAnimal),
((CRuntimeClass*)(&CAnimal::classCAnimal)),
NULL,
NULL
};
CRuntimeClass* CDog::GetRuntimeClass() const
{
// return RUNTIME_CLASS(CDog);
return ((CRuntimeClass*)(&CDog::classCDog));
}
结构体 CRuntimeclass
这个结构体主要关注第 1,2,4,5即可
struct CRuntimeClass
{
LPCSTR m_lpszClassName; // 类名称
int m_nObjectSize; // 类大小
UINT m_wSchema; // 类版本,固定值,0xFFFF
CObject* (PASCAL* m_pfnCreateObject)(); // 动态创建机制使用,这里为NULL
CRuntimeClass* m_pBaseClass; // 父类宏展开静态变量地址
CRuntimeClass* m_pNextClass; // 不适用为NULL
const AFX_CLASSINIT* m_pClassInit; // 不适用为NULL
}
属性 5 表示父类宏展开静态变量地址
这也就相当于构成了一个链表
函数?GetRuntimeClass()
返回本类成员 CRuntimeClass 结构体成员的地址
CRuntimeClass* CDog::GetRuntimeClass() const
{
// return RUNTIME_CLASS(CDog);
return ((CRuntimeClass*)(&CDog::classCDog));
}
总结
classCDog静态变量:保存为类名和类大小等信息,以及父类静态变量地址(负责连接链表)
GetRuntimeClass()虚函数:获取本类的静态变量地址(获取链表头结点)
执行过程分析
过程总结如下:
- 利用对象( yellowdog )的地址调用宏展开的虚函数GetRuntimeClass()获取本类静态变量的地址(链表头)
- 利用本类静态变量的地址(链表头)和目标进行比对。
- 如果相同,证明对象属于这个类。
- 如果不相同获取链表的下一个结点(父类静态变量地址)循环比对,只要有一次相同也能证明对象属于这个类。循环结束一次都没有比对成功,证明对象不属于这个类。
?
设置断点分析,函数内部this指针是 yellowdog;参数是CWnd类的结构体的地址
获取本类结构体CRuntimeClass的地址
CRuntimeClass* pClassThis = GetRuntimeClass();
调用函数IsDerivedFrom(pClass);参数是CWnd类的结构体CRuntimeClass的地址,this指针是yellowdog的结构体CRuntimeClass地址
return pClassThis->IsDerivedFrom(pClass);
如果两者相等返回TRUE
if (pClassThis == pBaseClass)
return TRUE;
就一直循环获取父类宏展开静态变量地址,也就是父类的CRuntimeClass结构体
直到遍历到CObject类,它的CRuntimeClass结构体属性5是NULL
否则,就返回FALSE,也就是isKindOf函数的结果
文章来源:https://blog.csdn.net/qq_61553520/article/details/135163769
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!