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;           // 类版本,固定值,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()虚函数:获取本类的静态变量地址(获取链表头结点)

执行过程分析

过程总结如下:

  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函数的结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MFC 动态创建机制

目录 动态创建机制概述 代码测试分析 执行过程 总结 动态创建机制概述 MFC 动态创建机制是 MFC 中的一项重要功能&#xff0c;它允许开发者在运行时动态创建和管理窗口控件。通过动态创建机制&#xff0c;开发者可以根据需要在程序运行过程中创建、显示和销毁窗口&#xf…

【K8S in Action】服务:让客户端发现pod 并与之通信(2)

一 通过Ingress暴露服务 Ingress (名词&#xff09; 一一进入或进入的行为&#xff1b;进入的权利&#xff1b;进入的手段或地点&#xff1b;入口。一个重要的原因是每个 LoadBalancer 服务都需要自己的负载均衡器&#xff0c; 以及 独有的公有 IP 地址&#xff0c; 而 Ingres…

基于STM32的DS1302实时时钟模块应用及原理介绍

在嵌入式系统中&#xff0c;实时时钟模块是一个常见的功能模块&#xff0c;用于记录和管理系统的时间信息。DS1302是一款低功耗、具有多种功能的实时时钟芯片&#xff0c;被广泛应用于各种电子产品中。本文将介绍基于STM32微控制器的DS1302实时时钟模块的应用及原理&#xff0c…

案例163:基于微信小程序的校园二手交易平台系统设计与开发

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

快速入门学习定时任务框架-xxljob

定时任务框架-xxljob 简介 主要用于分布式任务调度&#xff0c;可以将任务调度和执行分布在多个节点上。它提供了一个集中式的管理平台&#xff0c;支持动态添加、修改、删除任务&#xff0c;以及任务的分片执行&#xff0c;确保任务在分布式环境中的高可用性的一个框架 spr…

OSI 七层参考模型及TCP/IP 四层模型

OSI 七层参考模型 七层模型&#xff0c;亦称 OSI &#xff08; Open System Interconnection &#xff09;参考模型&#xff0c;即开放式系统互联。参考模型是国际标准化组织&#xff08;ISO &#xff09;制定的一个用于计算机或通信系统间互联的标准体系&#xff0c;一般称为…

在使用 npm install的时候提示node-sass command faile 解决方案

在使用npm install的时候错误提示node-sass 相关的。错误信息如下图&#xff1a; 解决方法&#xff08;PS&#xff1a;凯哥的不适用&#xff09; 出现这种问题基本是由于node版本与sass版本不匹配导致的 方案1&#xff1a;卸载node&#xff0c;安装对应版本 方案2&#xff1…

基于Arduino和HC-SR04的超声波测距系统设计

本文介绍了如何使用Arduino和HC-SR04超声波传感器设计并构建一个简单的超声波测距系统。我们将详细讨论硬件连线和编程步骤&#xff0c;并提供完整的Arduino代码。此系统可以应用于各种需要测量距离的项目&#xff0c;例如智能车辆、机器人和安防系统。 引言&#xff1a; 超声…

工具系列:PyCaret介绍_编写和训练自定义机器学习模型

文章目录 PyCaret安装PyCaret&#x1f449; 让我们开始吧&#x1f449; 数据集&#x1f449; 数据准备PyCaret中的设置函数&#x1f449; 可用模型&#x1f449; 模型训练与选择&#x1f449; 编写和训练自定义模型&#x1f449; GPLearn模型&#x1f449; NGBoost 模型&#x…

解决log4j多个日志都写到一个文件

之前客户端程序由于Websockt包依赖的log4j&#xff0c;就用log4j写日志了&#xff0c;Web用的log4j2没毛病。用log4j的多个logger的日志都写到一个文件里了&#xff0c;查了很多资料都没解决。今天闲了解决一下。 最后好使的配置 # 设置日志根 log4j.rootLogger INFO,Except…

嵌入式开发中利用strstr()对部分模块回传数据进行解析的问题(坑)

受到以下博文的启发&#xff1a; https://www.cnblogs.com/yup1983/p/11337837.html 验证&#xff1a; 最近通过ESP8266远程控制小车&#xff0c;在wifi回传的数据解析过程中遇到标题所述的烦恼 如上截图所示&#xff0c;数据回传过程中会接受到‘\0’字节对应的ASCII码为0x0…

基于IPP-FFT的线性调频Z(Chirp-Z,CZT)的C++类库封装并导出为dll(固定接口支持更新)

上一篇分析了三种不同导出C++类方法的优缺点,同时也讲了如何基于IPP库将FFT函数封装为C++类库,并导出为支持更新的dll库供他人调用。 在此基础上,结合前面的CZT的原理及代码实现,可以很容易将CZT变换也封装为C++类库并导出为dll,关于CZT的原理和实现,如有问题请参考: …

大数据应用开发1——配置基础环境

一、基础环境配置 1.配置虚拟网络 1.1、点击1、编辑2和3&#xff0c; 1.2、点开4&#xff0c;编辑网关 2、配置虚拟机环境 1.1、安装一台虚拟机&#xff0c;使用root用户登录&#xff0c;打开终端 1.2修改主机名 终端输入&#xff1a; vim /etc/hostname使用vim编辑/etc/ho…

MQ(消息队列)相关知识

1. 什么是mq 消息队列是一种“先进先出”的数据结构 2. 应用场景 其应用场景主要包含以下3个方面 应用解耦 系统的耦合性越高&#xff0c;容错性就越低。以电商应用为例&#xff0c;用户创建订单后&#xff0c;如果耦合调用库存系统、物流系统、支付系统&#xff0c;任何…

SpringMVC核心处理流程梳理

1、处理流程图展示 当我拿出这张图&#xff0c;阁下又该如何应对呢&#xff1f;执行流程是不是一目了然了。 2、DispatcherServlet&#xff1a;中央处理器或者中央调度器 下图官方的解释应该最完善了。 3、SpringMVC三大核心组件 HandlerMapping 处理器映射器&#xff0c;…

iApp最新版无服务器多功能软件库源码

无需服务器的多功能软件库源码分享&#xff0c;仅需添加一个后台应用和一个文档即可 使用教程如下&#xff1a; 在浏览器中打开理想后台地址&#xff1a;http://apps.xiaofei.run/user/ 如果没有账号&#xff0c;请注册一个免费账号。 登录账号后&#xff0c;添加一个后台应…

Oracle 学习(1)

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

微信小程序(uniapp)api讲解

Uniapp是一个基于Vue.js的跨平台开发框架&#xff0c;可以同时开发微信小程序、H5、App等多个平台的应用。下面是Uniapp常用的API讲解&#xff1a; Vue.js的API Uniapp采用了Vue.js框架&#xff0c;因此可以直接使用Vue.js的API。例如&#xff1a;v-show、v-if、v-for、comput…

类和对象

1 类定义&#xff1a; class ChecksumAccumulator {// class definition goes here } 你就能创建 ChecksumAccumulator 对象&#xff1a;new CheckSumAccumulator 注&#xff1a;1scala类中成员默认是public类型&#xff0c;若设为私有属性则必须加private关键字。在scala中是…

Defi安全-Mono攻击事件分析--etherscan+phalcon

MonoX攻击事件相关信息 在Ethereum和Polygon网络都发生了&#xff0c;攻击手段相同&#xff0c;以Ethereum为例进行分析&#xff1a; 攻击者地址&#xff1a;MonoX Finance Exploiter | Address 0xecbe385f78041895c311070f344b55bfaa953258 | Etherscan 攻击合约&#xff1a…