在揭开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. react,react-router,redux+react-redux 构建一个React Demo

    创建初始化应用 加速我们的npm. npm install -g cnpm --registry=https://registry.npm.taobao.org 利用create-react-app ...

  2. 从零开始react实战:云书签(总览)

    一个合格的全栈开发怎么能不会 react 呢?所以从现在开始系统的学习 react 开发.目标:完成完成一个云书签,包含前后台. 基于create-react-app进行开发,选择这个框架有以下两个原 ...

  3. 搞不懂JS中赋值·浅拷贝·深拷贝的请看这里

    前言 百科定义:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这 ...

  4. windows系统将Tomcat将控制台的日志重定向到日志文件

    1 . 修改startup.bat 将 56 行注释,加上一行: call "%EXECUTABLE%" run %CMD_LINE_ARGS% >> ..\logs\ ...

  5. echarts路径图 绘制上海市52路公交车线路

    busLines = [{"coords":[[121.494687,31.253937],[121.494276,31.254031],[121.494226,31.254042 ...

  6. Socket网络编程-TCP编程

    Socket网络编程-TCP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.socket介绍 1>.TCP/IP协议 2>.跨网络的主机间通讯 在建立通信连接的 ...

  7. 在ubuntu系统中,遇到 “由于/bin 不在PATH 环境变量中,故无法找到该命令”问题

    2018年01月07日 11:27:34 YangJianShuai 阅读数 3024更多 分类专栏: linux 好多命令的位置在/usr/bin.恢复办法如下:1. /usr/bin/sudo v ...

  8. git reset 的HEAD和--hard

    转载请注明来源https://www.cnblogs.com/sogeisetsu/p/11407764.html git reset 的HEAD和--hard git reset HEAD < ...

  9. Linux 修改时区(PDT修改为CST)

    方法1: Linux 修改时区 本文链接:https://blog.csdn.net/Aritem/article/details/79213306 命令:tzselect 按照顺序依次输入5,9,1 ...

  10. 第六篇 -- LINQ to XML

    一.LINQ to XML常用成员 LINQ to XML的成员, 属性列表: 属性 说明 Document 获取此 XObject 的 XDocument  EmptySequence  获取空的元 ...