MFC六大关键技术之运行时类型识别

MFC运行时类型识别(MFC RTTI)与动态创建.doc 立即下载

        运行时类型识别(RTTI)(Run-Time Type Identification)即是程序执行过程中知道某个对象属于某个类,我们平时用C++编程接触的RTTI一般是编译器的RTTI,即是在新版本的 VC++编译器里面选用“使能RTTI”,然后载入typeinfo.h文件,就可以使用一个叫typeid()的运算子,它的地位与在C++编程中的 sizeof()运算子类似的地方(包含一个头文件,然后就有一个熟悉好用的函数)。typdid()关键的地方是可以接受两个类型的参数:一个是类名 称,一个是对象指针。所以我们判别一个对象是否属于某个类就可以象下面那样:

if (typeid (ClassName)== typeid(*ObjectName)){
((ClassName*)ObjectName)->Fun();
}


   象上面所说的那样,一个typeid()运算子就可以轻松地识别一个对象是否属于某一个类,但MFC并不是用typeid()的运算子来进行动态类型识 别,而是用一大堆令人费解的宏。很多学员在这里很疑惑,好象MFC在大部分地方都是故作神秘。使们大家编程时很迷惘,只知道在这里加入一组宏,又在那儿加 入一个映射,而不知道我们为什么要加入这些东东。

  其实,早期的MFC并没有typeid()运算子,所以只能沿用一个老办法。我们甚至可以想象一下,如果MFC早期就有template(模板)的概念,可能更容易解决RTTI问题。

  所以,我们要回到“古老”的年代,想象一下,要完成RTTI要做些什么事情。就好像我们在一个新型(新型到我们还不认识)电器公司里面,我们要识别哪个是电饭锅,哪个是电磁炉等等,我们要查看登记的各电器一系列的信息,我们才可以比较、鉴别,那个东西是什么!
要登记一系列的消息并不是一件简单的事情,大家可能首先想到用数组登记对象。但如果用数组,我们要定义多大的数组才好呢,大了浪费空间,小了更加不行。所以我们要用另一种数据结构——链表。因为链表理论上可大可小,可以无限扩展。

  链表是一种常用的数据结构,简单地说,它是在一个对象里面保存了指向下一个同类型对象的指针。我们大体可以这样设计我们的类:

struct CRuntimeClass
{
……类的名称等一切信息……
CRuntimeClass * m_pNextClass;//指向链表中下一CRuntimeClass对象的指针
};


  链表还应该有一个表头和一个表尾,这样我们在查链表中各对象元素的信息的时候才知道从哪里查起,到哪儿结束。我们还要注明本身是由哪能个类派生。所以我们的链表类要这样设计:

struct CRuntimeClass
{
……类的名称等一切信息……
CRuntimeClass * m_pBaseClass;//指向所属的基类。
CRuntimeClass * m_pNextClass;//定义表尾的时候只要定义此指针为空就可以 了。
static CRuntimeClass* pFirstClass;//这里表头指针属于静态变量,因为我们知道static变量在内存中只初始化一次,就可以为各对象所用!保证了各对象只有一个表头。
};


  有了CRuntimeClass结构后,我们就可以定义链表了:

static CRuntimeClass classCObject={NULL,NULL};//这里定义了一个CRuntimeClass对象,


  因为classCObject无基类,所以m_pBaseClass为NULL。因为目前只有一个元素(即目前没有下一元素),所以m_pNextClass为NULL(表尾)。

   至于pFirstClass(表头),大家可能有点想不通,它到什么地方去了。因为我们这里并不想把classCObject作为链表表头,我们还要在 前面插入很多的CRuntimeClass对象,并且因为pFirstClass为static指针,即是说它不是属于某个对象,所以我们在用它之前要先 初始化:

CRuntimeClass* CRuntimeClass::pFirstClass=NULL;


   现在我们可以在前面插入一个CRuntimeClass对象,插入之前我得重要申明一下:如果单纯为了运行时类型识别,我们未必用到 m_pNextClass指针(更多是在运行时创建时用),我们关心的是类本身和它的基类。这样,查找一个对象是否属于一个类时,主要关心的是类本身及它 的基类:

CRuntimeClass classCCmdTarget={ &classCObject, NULL};
CRuntimeClass classCWnd={ &classCCmdTarget ,NULL };
CRuntimeClass classCView={ &classCWnd , NULL };


   好了,上面只是仅仅为一个指针m_pBaseClass赋值(MFC中真正CRuntimeClass有多个成员变量和方法),就连接成了链表。假设我 们现在已全部构造完成自己需要的CRuntimeClass对象,那么,这时候应该定义表头。即要用pFirstClass指针指向我们最后构造的 CRuntimeClass对象——classCView。

CRuntimeClass::pFirstClass=&classCView;


  现在链表有了,表头表尾都完善了,问题又出现了,我们应该怎样访问每一个CRuntimeClass对象?要判断一个对象属于某类,我们要从表头开始,一直向表尾查找到表尾,然后才能比较得出结果吗。肯定不是这样!

   大家可以这样想一下,我们构造这个链表的目的,就是构造完之后,能够按主观地拿一个CRuntimeClass对象和链表中的元素作比较,看看其中一个 对象中否属于你指定的类。这样,我们需要有一个函数,一个能返回自身类型名的函数GetRuntimeClass()。

  上面简单地说一下链表的过程,但单纯有这个链表是没有任何意义。回到MFC中来,我们要实现的是在每个需要有RTTI能力的类中构造一个CRuntimeClass对象,比较一个类是否属于某个对象的时候,实际上只是比较CRuntimeClass对象。

   如何在各个类之中插入CRuntimeClass对象,并且指定CRuntimeClass对象的内容及CRuntimeClass对象的链接,这里起 码有十行的代码才能完成。在每个需要有RTTI能力的类设计中都要重复那十多行代码是一件乏味的事情,也容易出错,所以MFC用了两个宏代替这些工作,即 DECLARE_DYNAMIC(类名)和IMPLEMENT_DYNAMIC(类名,基类名)。从这两个宏我们可以看出在MFC名类中的 CRuntimeClass对象构造连接只有类名及基类名的不同!

  到此,可能会有朋友问:为什么要用两个宏,用一个宏不可以代换 CRuntimeClass对象构造连接吗?个人认为肯定可以,因为宏只是文字代换的游戏而已。但我们在编程之中,头文件与源文件是分开的,我们要在头文 件头声明变量及方法,在源文件里实具体实现。即是说我们要在头文件中声明:

public:
static CRuntimeClass classXXX //XXX为类名
virtual CRuntime* GetRuntimeClass() const;


  然后在源文件里实现:

CRuntimeClass* XXX::classXXX={……};
CRuntime* GetRuntimeClass() const;
{ return &XXX:: classXXX;}//这里不能直接返回&classXXX,因为static变量是类拥有而不是对象拥有。


  我们一眼可以看出MFC中的DECLARE_DYNAMIC(类名)宏应该这样定义:

#define DECLARE_DYNAMIC(class_name) public: static CRuntimeClass class##class_name;
virtual CRuntimeClass* GetRuntimeClass() const;


  其中##为连接符,可以让我们传入的类名前面加上class,否则跟原类同名,大家会知道产生什么后果。

  有了上面的DECLARE_DYNAMIC(类名)宏之后,我们在头文件里写上一句:

DECLARE_DYNAMIC(XXX)


  宏展开后就有了我们想要的:

public:
static CRuntimeClass classXXX //XXX为类名
virtual CRuntime* GetRuntimeClass() const;


  对于IMPLEMENT_DYNAMIC(类名,基类名),看来也不值得在这里代换文字了,大家知道它是知道回事,宏展开后为我们做了什么,再深究真是一点意义都没有!

  有了此链表之后,就像有了一张存放各类型的网,我们可以轻而易举地RTTI。CObject有一个函数BOOL IsKindOf(const CRuntimeClass* pClass) const;,被它以下所有派生员继承。

  此函数实现如下:

BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
CRuntimeClass* pClassThis=GetRuntimeClass();//获得自己的CRuntimeClass对象指针。
while(pClassThis!=NULL)
{
if(pClassThis==pClass) return TRUE;
pClassThis=pClassThis->m_pBaseClass;//这句最关键,指向自己基类,再回头比较,一直到尽头m_pBaseClass为NULL结束。
}
return FALSE;
}

 

 

原文:

http://www.yesky.com/327/1915827.shtml

基于VC++的水果识别系统.zip 基于VC++的水果识别系统。。 立即下载

相关推荐

VC6.0MFC实现的网格图像图像识别

网格图像识别程序,MFC,VC6.0,还包括如灰度化,图像滤波等初级处理的功能

MFC中的RTTI(Runtime Type Identification, 运行时类型识别)详解(参考《深入浅出MFC》)

在MFC中的RTTI的实现,主要是利用一个名为CRuntimeClass的结构来链接各个“有关系的类”的信息来实现的。简单来说,就是在需要用到RTTI技术的类内建立CRuntimeClass的静态变量,来储存该类的相关信息(包括类名、基类的CRuntimeClass结构的指针、让“有关系的类”的信息形成链表的next指针、以及链表的首指针(静态)等信息)。

杨领well的专栏 4万+

SAPABAP金色传说:关于导入和导出Excel时反复弹窗提示 SAP GUI安全性问题的解决方法

文章目录前言一、提示的到底是什么?二、关闭SAP GUI安全提示的步骤1.设置位置 前言 如果你在SAP中,经常需要将数据导出Excel,或者使用Excel进行批导数据,那么你对下面这个频繁出现的弹窗提示一定不陌生! 系统试图创建文件 C:\Users\15265\Desktop\EXPORT.XLSX 于目录 C:\Users\15265\Desktop\ 是否要授权修改父目录及其所有子目录? 不管你是不是选的记住我的决定,它必出!就很烦!那如何处理才能关闭呢? 提示:以下是本篇文章正文内容,看完快

Easystudios博客 1万+

深入浅出mfc 运行时类型识别(RTTI 、DECLARE_DYNAMIC)、动态创建( DCLARE_DYNCREATE)、永久保存(DECLARE_SERIAL)

只有用DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的CObject的派生类才能返回CRuntimeClass结构指针。4. 程序的模块状态中有所有的RuntimeClass的列表,因此,查找对应的程序支持的RuntimeClass(对比ClassName),获得对应的RuntimeClass;//初始化一个名为"_init_##class_name"的AFX_CLASSINIT静态结构,主要作用是给指定的class_name的。

baidu_16370559的博客 1591

【论文精度】生成式预训练模型——BART(Bidirectional and Auto-Regressive Transformers)

​ BART是一个预训练的seq2seq的去噪自编码(denoising autoencoder)模型,BART以下方式进行训练①用任意的噪声函数(noising function)去破坏文本;②学习一个模型来重建原始文本。它使用一个标准的基于transformer的神经机器翻译架构,可以看作是BERT(双向编码器)、GPT(left-to-right解码器)以及其他预训练方案的推广。

weixin_45828972的博客 7450

SocraticLM: Exploring Socratic Personalized Teaching with Large Language Models

大型语言模型(LLM)被认为是推进智能教育的一项关键技术,因为它们展示了深入理解教学场景和为学生提供个性化指导的潜力。然而,当前个性化教学中基于LLM的应用主要遵循“问答”范式,学生被动地获得答案和解释。在本文中,我们提出了苏格拉底式教学模式(SocraticLM ),它实现了一种苏格拉底式的“发人深省”的教学范式,实现了真正的课堂教师的角色,让学生积极参与到真正掌握解决问题所需的思考过程中。

weixin_43961909的博客 2884

MFC中的运行时类型识别(RTTI)

RTTI是Runtime Type Identification的缩写,中文名为“运行时类型识别”。       MFC早在编译器支持RTTI之前,就有了这种能力。我们现在要以相同的手法,在Console程序中仿真出来。我希望我的类库具备IsKindOf 的能力,能在执行期侦测到某个对象是否属于某个类,并传回TRUE 或 FALSE。以形状 Shape为例 ,我希望:     即 长方

sanqima的专栏 1261

Altium Designer 16安装教程(Windows11、小白教程)

Altium Designer 16在Windows11中的超详细安装教程

qq_47003770的博客 1万+

MFC六大核心机制之二:运行时类型识别(RTTI)

上一节讲的是MFC六大核心机制之一:MFC程序的初始化,本节继续讲解MFC六大核心机制之二:运行时类型识别(RTTI)。        typeid运算子        运行时类型识别(RTTI)即是程序执行过程中知道某个对象属于某个类,我们平时用C++编程接触的RTTI一般是编译器的RTTI,即是在新版本的VC++编译器里面选用“使能RTTI”,然后载入typeinfo.h文件,就可

周小宇的专栏 853

小黄鸭机器人技术全解-第 07 章 关节自由度与行程参数

—鸭子歪着头转头时,转的平面是斜的,这正是它"灵动"感的来源。仿真里这是自动的(轴定义在父刚体系),复刻时不需要做任何事——

yolo模型训练找我,AI游戏合作找我 67

第133章 PCL OrientedBoundingBox 有向包围盒

中文叫有向包围盒,是一种旋转过的包围盒。特点:不像AABB那样固定朝向坐标轴能更紧密地包裹物体适用于复杂姿态的物体,比如倾斜、旋转的物体通常通过PCA、惯性矩等算法确定方向。

yumeiguo的博客 264

MFC六大关键技术之(二)——运行时类型识别(RTTI)

 MFC六大关键技术之(二)——运行时类型识别(RTTI)运行时类型识别(RTTI)即是程序执行过程中知道某个对象属于某个类,我们平时用C++编程接触的RTTI一般是编译器的RTTI,即是在新版本的VC++编译器里面选用“使能RTTI”,然后载入typeinfo.h文件,就可以使用一个叫typeid()的运算子,它的地位与在C++编程中的sizeof()运算子类似的地方(包含一个头文件,然

sunjd2001的专栏 6834

2026年中科曙光嵌入式软件岗位面试题库(附参考答案)

嵌入式系统与C/C++基础摘要 硬件与外设总线 SPI总线:高速全双工同步串行接口,采用SCLK、MOSI、MISO和CS信号线,支持一主多从架构,典型应用于Flash存储、传感器等高速外设。 I2C总线:两线制低速串行总线(SDA/SCL),支持多主多从,需注意地址冲突和信号完整性。 时序约束:包括建立时间、保持时间、时钟周期等,是保障电路稳定运行的关键。 AD转换:将模拟信号转换为数字信号,应用于传感器采集、音频处理等场景。 PC寄存器:存储下一条指令地址,控制程序执行流,在跳转和中断时自动更新。 C/

Open 69

深入浅出MFC学习笔记:MFC六大关键技术仿真之RTTI运行时类型识别

RTTI(运行时类型识别)    参考文献:深入浅出MFC-侯捷 怎样去构造类别型录网? 一、定义数据结构: 其中pFirstClass指针属于痊愈变量,所以它应该以static修饰之。 而且我们最终希望达到以下这样子的效果:构造成如下的类别型录  二、具体做法: 1.在头文件和cpp文件中放入两个神奇的宏:   (1)DECLARE宏的定义

newner的专栏 975

计算机组成原理(第三版)唐朔飞-第五章输入输出系统-课后习题

计算机组成原理(第三版)唐朔飞-第五章输入输出系统-课后习题

weixin_45735391的博客 6万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

MFC六大关键技术之运行时类型识别(RTTI)

MFC六大关键技术之运行时类型识别(RTTI) 运行时类型识别(RTTI)即是程序执行过程中知道某个对象属于某个类,我们平时用C++编程接触的RTTI一般是编译器的RTTI,即是在新版本的VC++编译器里面选用“使能RTTI”,然后载入typeinfo.h文件,就可以使用一个叫typeid()的运算子,它的地位与在C++编程中的sizeof()运算子类似的地方(包含一个头文件,然后就有一个熟

SimKon的专栏 585

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

MFC六大关键技术之运行时类型识别(RTTI)

什么是RTTI 运行时类型识别(RTTI)即是程序执行过程中知道某个对象属于某个类。 实现过程 定义CRuntimeClass结构体描述类别: struct CRuntimeClass { // Attributes LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; // schema number of the l

Earl的专栏 408

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

剖析MFC六大关键技术 二 运行时类型识别(RTTI)

运行时类型识别(RTTI)即是程序执行过程中知道某个对象属于某个类,我们平时用C++编程接触的RTTI一般是编译器的RTTI,即是在新版本的VC++编译器里面选用“使能RTTI”,然后载入typeinfo.h文件,就可以使用一个叫typeid()的运算子,它的地位与在C++编程中的sizeof()运算子类似的地方(包含一个头文件,然后就有一个熟悉好用的函数)。typdid()关键的地方是可以接受两

389

GBase 8c锁冲突与死锁排查实战:从定位到预防

数据库并发访问中,锁机制保障了事务的隔离性与一致性,但锁冲突和死锁却会导致业务阻塞甚至系统假死。理解锁的类型与冲突矩阵是高效排查的前提:表锁、行锁、事务锁各司其职,而`ACCESS EXCLUSIVE`等强锁会阻塞几乎所有操作。当大量会话堆积在`UPDATE`或`ALTER TABLE`上时,不应盲目优化慢SQL,而应通过`pg_locks`与`pg_stat_activity`视图定位持锁会话,借助`pg_blocking_pids()`梳理阻塞链。针对国产数据库GBase 8c,其内核与openGaus

weixin_34192816的博客 175
上一篇: OnDraw()和OnPaint()
下一篇: error LNK2019: 无法解析的外部符号 public: __thiscall
un_loading
博客等级 码龄17年 4粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值