MFC 运行时类信息机制

目录

运行时类信息机制概述

测试

宏代换分析

结构体 CRuntimeclass

函数 GetRuntimeClass()

总结

执行过程分析


运行时类信息机制概述

在程序运行过程中可以获知对象的类的相关信息(例如∶对象是否属于某个类)

如何使用?

  • 类必须派生自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;           // 类版本,固定值,0xFFFFCObject* (PASCAL* m_pfnCreateObject)();  // 动态创建机制使用,这里为NULLCRuntimeClass* m_pBaseClass;   // 父类宏展开静态变量地址CRuntimeClass* m_pNextClass;   // 不适用为NULLconst AFX_CLASSINIT* m_pClassInit; // 不适用为NULL
}

属性 5 表示父类宏展开静态变量地址

这也就相当于构成了一个链表

函数 GetRuntimeClass()

返回本类成员 CRuntimeClass 结构体成员的地址

CRuntimeClass* CDog::GetRuntimeClass() const
{//	return RUNTIME_CLASS(CDog); return ((CRuntimeClass*)(&CDog::classCDog));
}

总结

classCDog静态变量:保存为类名和类大小等信息,以及父类静态变量地址(负责连接链表)

GetRuntimeClass()虚函数:获取本类的静态变量地址(获取链表头结点)

执行过程分析

过程总结如下:

  1. 利用对象( yellowdog )的地址调用宏展开的虚函数GetRuntimeClass()获取本类静态变量的地址(链表头)
  2. 利用本类静态变量的地址(链表头)和目标进行比对。
  3. 如果相同,证明对象属于这个类。
  4. 如果不相同获取链表的下一个结点(父类静态变量地址)循环比对,只要有一次相同也能证明对象属于这个类。循环结束一次都没有比对成功,证明对象不属于这个类。
     

设置断点分析,函数内部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函数的结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/298024.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Real-Time Volumetric Cloudscapes

实时体积云景 GPU Pro 7 实时体积云景的翻译 4.1 概览 游戏中的实时体积云通常为了提高渲染效率而降低质量。最成功的方法仅限于低空蓬松半透明的层状云。我们提出了一种体积解决方案&#xff0c;可以使用不断变化并且逼真的结果填充天空&#xff0c;来描绘高海拔卷云和所有…

OpenGL 绘制Mesh数据(Qt)

文章目录 一、简介二、实现代码三、实现效果一、简介 Mesh数据的结构主要就是点与三角面片,因此本质上仍然是对三角面片进行绘制。这里我们借助VCG这个库实现对Mesh数据的读取,这个库相对简单轻巧,很方便使用。 二、实现代码 由于修改的部分很多,我们逐一进行解释一下: --…

[原创][R语言]股票分析实战[4]:周级别涨幅趋势的相关性

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

bean生命周期源码(三)

书接上文 文章目录 一、Bean的销毁逻辑1. 简介2. Bean销毁逻辑的注册3. Bean的销毁过程 一、Bean的销毁逻辑 1. 简介 前面我们已经分析完了Spring创建Bean的整个过程的源码&#xff0c;在创建bean的核心方法中doCreateBean这一个核心方法中&#xff0c;在方法的最后面有这么…

编程规范:长函数的思考

在工作&#xff0c;我们应该都不想看到非常的长函数。对于一个运行5年左右的项目&#xff0c;极有可能出现这种情况。由于长函数的长、if/else嵌套&#xff0c;导致代码的可读性非常差&#xff0c;这对于项目的维护和开发带来了极大的困难。所以我们应该避免写长函数&#xff0…

智能优化算法应用:基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.法医调查算法4.实验参数设定5.算法结果6.…

Oracle 学习(1)

Oracle简介 Oracle是殷墟&#xff08;yīn Xu&#xff09;出土的甲骨文&#xff08;oracle bone inscriptions&#xff09;的英文翻译的第一个单词&#xff0c;在英语里是“神谕”的意思。Oracle公司成立于1977年&#xff0c;总部位于美国加州&#xff0c;是世界领先的信息管…

C++面试宝典第9题:找出第K大元素

题目 给定一个整数数组a,同时给定它的大小N和要找的K(1 <= K <= N),请根据快速排序的思路,找出数组中第K大的数(保证答案存在)。比如:数组a为[50, 23, 66, 18, 72],数组大小N为5,K为3,则第K大的数为50。 解析 这道题主要考察应聘者对于快速排序的理解,以及实…

配置手工模式链路聚合示例(交换机之间直连)

组网图形 图1 配置手工模式链路聚合组网图 手工模式链路聚合简介配置注意事项组网需求配置思路操作步骤配置文件 手工模式链路聚合简介 以太网链路聚合是指将多条以太网物理链路捆绑在一起成为一条逻辑链路&#xff0c;从而实现增加链路带宽的目的。链路聚合分为手工模式和LA…

java调用GDAL实现栅格数据的重采样的一种方法

目录 1.关于重采样 1.1概念 1.2用途 1.3常见算法 2.关于GDAL 2.1GDAL中的重采样算法 3.实现重采样 3.1思路 3.2完整代码 3.3使用QGIS验证效果 1.关于重采样 1.1概念 重采样是以原始图像的像元值或者导出的值填充到新的图像的每个像元的的过程。 1.2用途 在地理信…

顺序表的介绍与简单运用

1&#xff1a;解释与结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存 储。在数组上完成数据的增删查改。 顺序表一般可分为一下几类 1.1 静态顺序表 概念&#xff1a;使用定长数组存储元素。注意&#xff1a;这种是…

YOLOv8改进 | 主干篇 | 利用SENetV2改进网络结构 (全网首发改进)

一、本文介绍 本文给大家带来的改进机制是SENetV2&#xff0c;其是2023.11月的最新机制(所以大家想要发论文的可以在上面下点功夫)&#xff0c;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何…