如何在运行时确定对象类型(RTTI)

2016-01-29 12:19 31 1 收藏

如何在运行时确定对象类型(RTTI),如何在运行时确定对象类型(RTTI)

【 tulaoshi.com - C语言心得技巧 】

如何在运行时确定对象类型(RTTI)

作者:NorthTibet

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)



    RTTI 是“Runtime Type Information”的缩写,意思是:运行时类型信息。它提供了运行时确定对象类型的方法。本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI;本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和 dynamic_cast。
    其实,RTTI 在C++中并不是什么新的东西,它早在十多年以前就已经出现了。但是大多数开发人员,包括许多高层次的C++程序员对它并不怎么熟悉,更不用说使用 RTTI 来设计和编写应用程序了。
    一些面向对象专家在传播自己的设计理念时,大多都主张在设计和开发中明智地使用虚拟成员函数,而不用 RTTI 机制。但是,在很多情况下,虚拟函数无法克服本身的局限。每每涉及到处理异类容器和根基类层次(如 MFC)时,不可避免要对对象类型进行动态判断,也就是动态类型的侦测。如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast。
    首先让我们来设计一个类层次,假设我们创建了某个处理文件的抽象基类。它声明下列纯虚拟函数:open()、close()、read()和 write():

class File{public: virtual int open(const string & filename)=0; virtual int close(const string & filename)=0; // virtual ~File()=0; // 记住添加纯虚拟析构函数(dtor)};
现在从 File 类派生的类要实现基类的纯虚拟函数,同时还要提供一些其他的操作。假设派生类为 DiskFile,除了实现基类的纯虚拟函数外,还要实现自己的flush()和defragment()操作:
class DiskFile: public File{public: int open(const string & filename); // 实现其他的纯虚拟函数    ...... // 自己的专有操作 virtual int flush(); virtual int defragment();};    
接着,又从 DiskFile 类派生两个类,假设为 TextFile 和 MediaFile。前者针对文本文件,后者针对音频和视频文件:
class TextFile: public DiskFile{  // ......  int  sort_by_words();};class MediaFile: public DiskFile{  //......};        
我们之所以要创建这样的类层次,是因为这样做以后可以创建多态对象,如:
File *pfile; // *pfile的静态类型是 Fileif(some_condition)  pfile = new TextFile; // 动态类型是 TextFileelse  pfile = new DiskFile; // 动态类型是 DiskFile       
    假设你正在开发一个基于图形用户界面(GUI)的文件管理器,每个文件都可以以图标方式显示。当鼠标移到图标上并单击右键时,文件管理器打开一个菜单,每个文件除了共同的菜单项,不同的文件类型还有不同的菜单项。如:共同的菜单项有“打开”“拷贝”、和“粘贴”,此外,还有一些针对特殊文件的专门操作。比如,文本文件会有“编辑”操作,而多媒体文件则会有“播放”菜单。为了使用 RTTI 来动态定制菜单,文件管理器必须侦测每个文件的动态类型。利用 运算符 typeid 可以获取与某个对象关联的运行时类型信息。typeid 有一个参数,传递对象或类型名。因此,为了确定 x 的动态类型是不是Y,可以用表达式:typeid(x) == typeid(Y)实现:
#include <typeinfo // typeid 需要的头文件void menu::build(const File * pfile){ if (typeid(*pfile)==typeid(TextFile)) {  add_option("edit");  } else if (typeid(*pfile)==typeid(MediaFile)) { add_option("play");  }}      
    使用 typeid 要注意一个问题,那就是某些编译器(如 Visual C++)默认状态是禁用 RTTI 的,目的是消除性能上的开销。如果你的程序确实使用了 RTTI,一定要记住在编译前启用 RTTI。使用 typeid 可能产生一些将来的维护问题。假设你决定扩展上述的类层次,从MediaFile 派生另一个叫 LocalizeMedia 的类,用这个类表示带有不同语言说明文字的媒体文件。但 LocalizeMedia 本质上还是个 MediaFile 类型的文件。因此,当用户在该类文件图标上单击右键时,文件管理器必须提供一个“播放”菜单。可惜 build()成员函数会调用失败,原因是你没有检查这种特定的文件类型。为了解决这个问题,你必须象下面这样对 build() 打补丁:
void menu::build(const File * pfile){ //......  else if (typeid(*pfile)==typeid(LocalizedMedia)) {  add_option("play");   }}     
    唉,这种做法真是显得太业余了,以后每次添加新的类,毫无疑问都必须打类似的补丁。显然,这不是一个理想的解决方案。这个时候我们就要用到 dynamic_cast,这

来源:https://www.tulaoshi.com/n/20160129/1485621.html

延伸阅读
  Public Class Resize     '移动了吗?     Private IsMoving As Boolean = False     '控件最后的宽     Private ctrlLastWidth As Integer = 0     '控件最后的高     Private ctrlLastHeight As Integer =...
标签: 浏览器
IE浏览器如何解决运行时间错误   出现了运行时间错误的解决办法: 降低IE安全级别,启用ActiveX 控件,关闭脚本调试; 第一步:首先打开IE浏览器,点击上方的工具菜单选择Internet选项在常规选项中点击删除Cookies点击确定再点击删除文件勾选删除所有脱机内容,点击确定不要关闭Internet选项窗口; 第二步:切换到...
飞信登录报C++运行时错误 故障现象: 登录时出现报错 原因分析: 原来安装过飞信,系统当中有之前的飞信文件存在。 解决方案: 在我的文档那个文件夹里,把那个叫fetion的文件夹删掉就可以了。
标签: Web开发
在您的IE浏览器上运行含有JavaScript代码的页面时都会产生一个警告。这个警告确实很烦人,不知情的人看了还以为是病毒什么呢,很容易让人产生误解! 记得网上也有人称其为IE的小黄条警告。具体的什么叫法我们今天不用关心,我们关心的是如何去掉这个警告。具体方法如下: 点击工具---Internet选项---高级---"允许活动的内容在我的...
     如何获得程序或者一段代码运行的时间?你可能说有专门的程序测试工具,确实,不过你也可以在程序中嵌入汇编代码来实现。      在Pentium的指令系统中有一条指令可以获得CPU内部64位计数器的值,我们可以通过代码两次获取该计数器的值而获得程序或代码运行的时钟周期数,进而通过你的cpu的频率算...

经验教程

709

收藏

70
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部