在揭开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常用代码2

    用matplotlib画图时,若设置全部行输出,会得到包括图标在内的所有输出结果. plt.show() 输出全部行,参数为“all”:输出最后一行,参数为“last_expr”

  2. MAC电脑下Appium + python3 + robotframework ios的真机测试环境搭建

    本人的环境搭建前的准备,MAC电脑一台(macOS Mojave 10.14.0及以上),Xcode 10.0及以上   ,自己注册的一个Apple ID 账户,必须你的电脑能连接互联网,最好不要用公 ...

  3. vue中自定义指令

    //vue中自定义指令 //使用 Vue.directive(id, [definition]) 定义全局的指令 //参数1:指令的名称.注意,在定义的时候,指令的名称前面,不需要加 v-前缀; 但是 ...

  4. js多个参数(追加参数)

    /** * 多个参数 * @param fn * @param args * @param scope */ function multipleArguments(fn,args,scope){ if ...

  5. 剑指前端(前端入门笔记系列)——DOM(元素大小)

    DOM——元素大小   DOM中没有规定如何确定页面中与元素的大小,IE率先映入了一些属性来确定页面中元素的大小,以便开发人员使用,目前,所有主要的浏览器都已经支持这些属性了.   1.偏移量(单位为 ...

  6. js中 json对象与json字符串相互转换的几种方式

    以下总结js中 json对象与json字符串相互转换的几种方式: 一.JSON对象转化为JSON字符串 1.使用JSON.stringify()方法进行转换 该方法不支持较老版本的IE浏览器,比如:i ...

  7. Solr基础知识三(整合SSM)

    前两篇讲了solr安装和导入数据,这篇讲如何整合到SSM中. 一.整合SSM 1.1 引入依赖 1.2 初始化solr 1.3 写service 1.4 写控制层 1.5 查询 二.IK分词器 2.1 ...

  8. JS 基本操作

    1.判断数据是否包含某些数据 var ary=[{age:20,name:"a"},{age:20,name:"b"},,{age:30,name:" ...

  9. 查看Linux的本机IP

    命令式 ifconfig -a 在限制inet addr中显示本机的ip地址

  10. 行业——5G

    1.  概述 1.1  定义 5G:5th Generation Mobile Networks / 5th Generation Wireless Systems,第5代移动通信技术 1.2  商标 ...