C++为了能够在运行时正确判断一个对象确切的类型,加入了RTTI和type_info.

type_info

为每一个类型增加一个type_info对象。

为了能够在运行时获得对象的类型信息type_info,C++增加了两个运算符:typeid 和 dynamic_cast<>。type_info 常用的三个成员函数是 operator==()、operator!=() 和 name(),请参考标准头文件<typeinfo>.

typeid 运算符

它以一个对象或者类型名作为参数,返回一个匹配的const type_info对象,它表明该对象的确切类型.

void DeviceControllor::ControlThem(HomeElectricDevice& device)
{
Command cmd = GetCommand(); switch(cmd)
{
case PLAY_CD:
if(typeid(device) == typeid(Television))
{
Television* pTmp = static_cast<Television*>(&device);
pTmp->PlayVCD();
}
}
}

上面代码中:

typeid(device)返回一个type_info对象的引用-该对象持有与device对象相关的必要的运行时信息。

typeid(Television)则返回与类Television相关的类型信息。

当typeid()作用于一个类名而不是一个对象的时候,它总是返回一个对应于该类名的type_info对象。

dynamic_cast<>运算符  

typeid()不具备可扩展性,因为它返回一个对象的确切类型而不是基类型。一个派生类对象在语义上也应该是其基类型的对象(如果是public继承),然而typeid()不具备这种判断能力。

dynamic_cast<>能够自动识别对象与类型间is-a的关系。

dynamic_cast<dest_type>(src)

dest_type就是转换的目标类型,而src则是被转换的对象。其行为可以这样描述:如果运行时src和dest_type确实存在is-a关系,则转换可进行;否则转换失败。

  1. dynamic_cast<>可以用来转换指针和引用,但是不能转换对象。
  • 当目标类型是某种类型的指针(包括void*)时,如果转换成功则返回目标类型的指针,否则返回NULL;
  • 当目标类型为某种类型的引用时,如果成功则返回目标类型的引用,否则抛出std::bad_cast异常,因为不存在NULL引用。

2.  dynamic_cast<>如何能够知道一个基类型指针指向的对象是不是一个派生类对象呢?显然,它一定是通过该对象的vptr检查位于其类型的vtable第一个slot的type_info对象而得知的(见下图),或者不同的编译器对RTTI有不同的实现手段。因此dynamic_cast<>只能用于多态类型对象(拥有虚函数或虚拟继承),否则将导致编译器错误。

dynamic_cast<>可以实现两个方向的转换:upcast 和 downcast.

  • upcast:把派生类型的指针、引用转换成基类型的指针或引用(实际上这可以隐式地进行,不必显示地转换).
  • downcast:把基类型的指针或引用转换成派生类型的指针或引用。如果这个基类型的指针或引用确实指向一个这种派生类的对象,那么转换就会成功,否则转换就会失败。

当你使用RTTI时要注意如下事项:

  • 如果你的编译器没有打开RTTI支持,那么请打开它
  • 要想使用RTTI,对象所属类型必须是多态
  • 如果要用dynamic_cast<>转换一个引用,你要保证程序有一条catch()语句来处理std::bad_cast异常
  • 如果试图用typeid来检索NULL指针所指对象的类型信息,将抛出std::bad_typeid异常,像这样:typeid(*p);//p==NULL
  • 当用dynamic_cast<>转换一个指针的时候,要记住检查返回值是否为NULL。

最后,来总结一下RTTI背后的实现机制:

      无论基本类型还是用户定义类型,都需要额外的内存来存放type_info对象。

  多态类的type_info对象是如何存放的?要给每一个多态类增加一个指针成员,一个type_info对象,以及给虚函数表增加一项。该方法对任何多态类都是一样的,与程序中对象的个数无关。因此,使用typeid()来检索每个对象运行时的类型信息所花时间是一样的(通过vptr间接完成)。

     同任何其他对象一样,type_info对象的创建过程也需要时间。

     RTTI要求程序维护一颗继承树,dynamic_cast<>能够判断源对象与目标类型之间是否具有is-a关系,这需要在运行时遍历继承树,并且其开销会随着源对象类型与目标类型之间距离(层次)的增大而增大。

RTTI(运行时类型识别)的更多相关文章

  1. RTTI 运行时类型识别 及异常处理

    RTTI   运行时类型识别 typeid  ------  dynamic_cast dynamic_cast 注意事项: 1.只能应用于指针和引用之间的转化 2.要转换的类型中必须包含虚函数 3. ...

  2. 框架原理第二讲,RTTI,运行时类型识别.(以MFC框架讲解)

    框架原理第二讲,RTTI,运行时类型识别.(以MFC框架讲解) 一丶什么是RTTI,以及RTTI怎么设计 通过第一讲,我们知道了怎么样升成一个窗口了,以及简单的消息循环. 第二讲则是主要讲解RTTI ...

  3. MFC原理第三讲.RTTI运行时类型识别

    MFC原理第三讲.RTTI运行时类型识别 一丶什么是RTTI RTTI. 运行时的时候类型的识别. 运行时类型信息程序.能够使用基类(父类)指针 或者引用 来检查这些指针或者引用所指的对象. 实际派生 ...

  4. Java基础之RTTI 运行时类型识别

    运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息. 多态(polymorphism)是基于R ...

  5. RTTI(运行时类型识别),typeid,dynamic_cast

    dynamic_cast注意: 1.只能应用于指针和引用的转换: 2.要转换的类型中必须包含虚函数: 3.转换成功则返回地址,如果失败则返回NULL: 参见项目:RTTI

  6. RTTI (Run-Time Type Identification,通过运行时类型识别) 转

    参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   RTTI提供了以下两个 ...

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

    上一节讲的是MFC六大核心机制之一:MFC程序的初始化,本节继续讲解MFC六大核心机制之二:运行时类型识别(RTTI). typeid运算子 运行时类型识别(RTTI)即是程序执行过程中知道某个对象属 ...

  8. RTTI(运行时类型识别)

    运行时类型识别(Run-time type identification , RTTI),是指在只有一个指向基类的指针或引用时,确定所指对象的准确类型的操作.其常被说成是C++的四大扩展之一(其他三个 ...

  9. C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

    运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast. 1. typeid操作符的实现 1.1. ...

随机推荐

  1. where条件使用to_char条件太慢

    where条件使用to_char 会不使用索引并使用nestedloop 可以用with as解决 最后再加上to_char的条件语句

  2. 转:iBatis简单入门教程

    iBatis 简介: iBatis 是apache 的一个开源项目,一个O/R Mapping 解决方案,iBatis 最大的特点就是小巧,上手很快.如果不需要太多复杂的功能,iBatis 是能够满足 ...

  3. 山寨"每日故宫"应用的图层遮罩效果

    山寨"每日故宫"应用的图层遮罩效果 最终效果: 应用中的效果: 素材图片: 源码: // // ViewController.m // 每日故宫 // // Created by ...

  4. Python读写oracle数据库

    最近项目中需要用到Python调用oracle实现读写操作,踩过很多坑,历尽艰辛终于实现了.性能怎样先不说,有方法后面再调优嘛.现在把代码和注意点记录一下. 1. 所需Python工具库 cx_Ora ...

  5. 如何修改PPT中左下方状态栏的主题名称

    网上有很多很好的PPT,可惜一般作者都加了名字和主题,现在我们就来说说如何修改PPT中左下方状态栏的主题名称. 如下图所示,红色方框内就是别人设置的主题. 网上很多网友都说:点击"视图&qu ...

  6. Lonely(非洲NANA作品)

    Lonely(非洲NANA作品) 编辑 Lonely NANA,出生于1968年10月5日的非洲加纳.来自于加纳的NANA出身于一个富有的家庭,但是父亲在他小时候离他们而去,母亲带着年幼的NANA定居 ...

  7. pthread线程内存布局

    http://www.cnblogs.com/snake-hand/p/3148191.html 我们从图上可以看出,两个线程之间的栈是独立的,其他是共享的,所以,在操作共享区域的时候才有可能出现同步 ...

  8. Android 4.4中AudioRecord用例 - 录制系统内置声音

    通过API 19新加的MediaRecorder.AudioSource.REMOTE_SUBMIX參数能够让系统App录制系统内置的声音,也就是扬声器的声音.以下是一个巨简单的样例来演示样例怎样通过 ...

  9. VM下,装centos7系统,配置nginx的问题

    一.流程 1.先安装nginx依赖的包 (1)yum install gcc-c++ (2)yum install -y pcre pcre-devel (3)yum install -y zlib ...

  10. WebForm下的$.ajax中contentType: “application/json” 的用法

    不使用contentType: “application/json”则data可以是对象 $.ajax({ url: actionurl, type: "POST", datTyp ...