在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。
    dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。下面就开始今天我们的话题:typeid。
   
    typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义,稍后我们看一下vs和gcc库里面的源码),它的表达式有下图两种形式。
   
   
    如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。
    ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作(在之后的章节中我会来分析type_info类文件的源码):

 t1 == t2  如果两个对象t1和t2类型相同,则返回true;否则返回false
 t1 != t2  如果两个对象t1和t2类型不同,则返回true;否则返回false
 t.name()  返回类型的C-style字符串,类型名字用系统相关的方法产生
 t1.before(t2)  返回指出t1是否出现在t2之前的bool值

type_info类提供了public虚
析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符(由此可见,如果把typeid看作函数的话,其应该是type_info的
友元)。type_info的name成员函数返回C-style的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这具体由编译器的实现所决定的,标准只要求实现为每个类型返回唯一的字符串。

    上面的都是一些理论的东西,看不真切,下面将通过代码和图例来展示。

;
}

我分别用MS的V8和GUN的GCC编译该段代码并运行,结果分别为下面的左右二图。
     
    对比代码以及上面的文字描述,不知道各位是否已经有所明了(这里需要注意的是Base类的对象b和对象指针pb,他们的输出)。
    考虑到V8的输出很直观,所以我采用V8来做实验。下面对上面的代码稍微添加一点内容,如下:

Base *pb2 = dynamic_cast<Base *>(new Derived);
Base &b2 = d;
Base *pb3 = &d;
cout << typeid(pb2).name() <<endl//输出Base *
     << typeid(b2).name()<<endl //输出Base
     << typeid(pb3).name()<<endl//输出Base *
     << typeid(*pb3).name()<<endl;//输出Base

因为Base不包含虚函数,所以typeid的结果指出,表达式的类型是Base或Base *型,尽管他们的底层对象是Derived。即:当typeid操作符的操作数是不带有虚函数的类类型时,typeid操作符会指出操作数的类型,而不是底层对象的类型。
   
    下面在对Base函数做一个小小调整,为其加上一个虚函数,再看输出结果。

class Base {virtual void f(){}; };
/*...*/
cout << typeid(pb2).name()
<<endl//输出Base *
     <<
typeid(b2).name()<<endl //输出Derived
     <<
typeid(pb3).name()<<endl//输出Base *
     <<
typeid(*pb3).name()<<endl;//输出Derived

这次Base含有虚函数,注意看结果,指针仍然是Base*的,尽管他们指向的是底层对象Derived,而这些Base对象的类型却是Derived的。
    因为指针pb3不是类类型,所以typeid就返回该指针pb3的指针类型Base *。而*pb3是一个类类型的表达式,而且该类带有虚函数,所以指出该pb3指向的底层对象的类型Derived。
    如果typeid操作符的操作数是至少包含一个虚拟函数的类类型时,并且该表达式是一个基类的引用,则typeid操作符指出底层对象的派生类类型。
    好了,文篇到此结束,留下几道小题目吧。

//采用V8环境
cout<< typeid(7.84) <<endl
    << typeid(Base*) <<endl
    << typeid(&pb3) <<endl;

感谢: http://blog.programfan.com/article.asp?id=45931

转自【http://www.cppblog.com/smagle/archive/2010/05/14/115286.html

【转】gdb typeid 详解的更多相关文章

  1. typeid详解(转)

    (http://www.cppblog.com/smagle/archive/2010/05/14/115286.html) 在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time ...

  2. GDB教程详解

    GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC ...

  3. typeid详解

    在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“ ...

  4. GDB调试详解

    GDB是一个由GNU开源组织发布的.UNIX/LINUX操作系统下的.基于命令行的.功能强大的程序调试工具. GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调 ...

  5. linux c/c++ GDB教程详解

    学习使用了GDB一段时间后,发现它真的好强大!好用! GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在U ...

  6. linux c/c++ GDB教程详解(转)

    http://www.gnu.org/manual/ http://www.gnu.org/software/gdb/documentation/ http://sourceware.org/gdb/ ...

  7. C语言-gdb调试工具详解

    回车 重复上一次命令 产生可调试的可执行文件:gcc -g main.c -o main, 必须加上-g选线, 表示在可执行文件中加入源文件信息, 但并不是将源文件嵌入可执行文件, 所以在调试时必须保 ...

  8. 【Linux】GDB用法详解(5小时快速教程)

    GDB是一个强大的命令行调试工具.虽然X Window提供了GDB的图形版DDD,但是我仍然更钟爱在命令行模式下使用GDB.大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本. UNIX下的软 ...

  9. 【Linux】【Commands】trouble shooting命令详解目录

    1. 简介 1.1. 最近看到阿里的运维招聘需要熟练掌握以下的命令,我就针对这几个命令做一下总结,有些命令我觉得别人总结的挺好了,我就不赘述了 1.2. 还有一些其他我觉得用得到的命令的用法会在第三部 ...

随机推荐

  1. python爬虫之Scrapy学习

    在爬虫的路上,学习scrapy是一个必不可少的环节.也许有好多朋友此时此刻也正在接触并学习scrapy,那么很好,我们一起学习.开始接触scrapy的朋友可能会有些疑惑,毕竟是一个框架,上来不知从何学 ...

  2. JS调用栈的一些总结

    原文地址 调用栈 调用栈是解释器追踪函数执行流的一种机制.当执行环境中调用了多个函数函数时,通过这种机制,我们能够追踪到哪个函数正在执行,执行的函数体中又调用了哪个函数. 我们知道JavaScript ...

  3. jQuery中的DOM操作(三)

    一.查找节点    [返回jQuery对象]$(选择器字符串);    使用jQuery函数,里面参数为选择器字符串,查询符合条件的BOM对象并返回jQuery对象eg: $('div.one spa ...

  4. 16、css实现div中图片占满整个屏幕

    <div class="img"></div> .img{ background: url("../assets/image/img.png&qu ...

  5. springboot+MessageSource实现国际化

    1.springboot自带,不需要引入任何依赖 2.在resource下建立:i18n/messages.properties 3.在application.yml增加以下内容 spring: ap ...

  6. Gzip模块

    Gzip模块为python的压缩和解压缩模块,读写gzip 文件 一.使用gzip模块压缩文件: 1 import gzip #导入python gzip模块,注意名字为全小写 2 g = gzip. ...

  7. zabbix--邮件告警

    zabbix 邮件告警机制 通过腾讯企业邮箱进行告警通知等.邮箱服务器账号需要在邮箱设置里面进行设置,开通ssl认证及专用密码 参考官档:https://www.zabbix.com/document ...

  8. go mod开发模式设置

    文章要解决的仅仅是一个问题 当你使用go get 无论如何get不到所需的包的问题 第一步就是下载goland 新手极其推荐goland,因为直接使用gland几乎没有挫败感,使用其他工具可能要折腾好 ...

  9. 最长上生子序列LIS

    学习动态规划问题(DP问题)中,其中有一个知识点叫最长上升子序列(longest  increasing subsequence),也可以叫最长非降序子序列,简称LIS.简单说一下自己的心得. 我们都 ...

  10. Codeforces K. Ice Skating(求强连通分量)

    题目描述: Ice Skating time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...