typeid详解

【深度C++】之“typeid与type_info” typeid与type_info。 阅读详情
    在揭开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的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这 具体由编译器的实现所决定的,标准只要求实现为每个类型返回唯一的字符串。

    上面的都是一些理论的东西,看不真切,下面将通过代码和图例来展示。
    
#include  < iostream >
using   namespace  std;

class  Base {};
class  Derived:  public  Base {};

int  main()
{
    Base b, *pb;
    pb = NULL;
    Derived d;

    cout 
<<  typeid( int ).name()  <<  endl
         
<<  typeid(unsigned).name()  <<  endl
         
<<  typeid( long ).name()  <<  endl
         
<<  typeid(unsigned  long ).name()  <<  endl
         
<<  typeid( char ).name()  <<  endl
         
<<  typeid(unsigned  char ).name()  <<  endl
         
<<  typeid( float ).name()  <<  endl
         
<<  typeid( double ).name()  <<  endl
         
<<  typeid( string ).name()  <<  endl
         
<<  typeid(Base).name()  <<  endl
         
<< typeid(b).name()<<endl
         << typeid(pb).name()<<endl
         << typeid(Derived).name() << endl
         << typeid(d).name()<<endl

         
<<  typeid(type_info).name()  <<  endl;
         
    
return   0 ;
}

    我分别用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
c++关键字之typeid typeid是 C++ 中用于获取运行时类型信息的操作符,主要通过返回对象来实现。可以用于判断对象的类型,尤其在多态场景中,有助于实现动态类型检查和运行时类型比较。使用时要注意多态性要求和对空指针的处理,避免意外的异常抛出。通过使用typeid,可以在运行时检查对象的类型,对于处理多态对象、调试代码以及实现更复杂的动态类型逻辑非常有用,但要注意不同编译器对type_info的实现细节可能有所不同,特别是name()方法返回的字符串表示。 阅读详情

相关推荐

Qt——元对象和属性机制

元对象(meta object)意思是描述另一个对象结构的对象,比如获得一个对象有多少成员函数,有哪些属性。在Qt中,我们将要用到的是QMetaObject这个类。

QtCompany的博客 691

typeid -- study

在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。    dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的

随缘,随心 1183

深度学习、图像分类入门,从VGG16卷积神经网络开始

刚开始接触深度学习、卷积神经网络的时候非常懵逼,不知道从何入手,我觉得应该有一个进阶的过程,也就是说,理应有一些基本概念作为奠基石,让你有底气去完全理解一个庞大的卷积神经网络: 本文思路: 一、我认为学习卷积神经网络必须知道的几个概念: 1、卷积过程:   我们经常说卷积神经网络卷积神经网络,到底什么才是卷积?网络层卷积过程到底怎么实现?我们在这里借鉴了另一位博客大牛的动态图来给大

Errors_In_Life的博客 16万+

C++ typeid关键字详解

C++ typeid关键字详解

路过的熊的博客 6615

5分钟搞懂超分算法:从插值到深度学习的实战对比(附Python代码)

本文系统对比了从传统插值到深度学习的主流超分算法,包括最近邻、双线性、双三次插值,以及基于边缘、统计模型和SRCNN、ESPCN、SRGAN等深度学习模型。通过实战代码和决策框架,帮助开发者根据图像质量、速度、资源等需求,快速选择最合适的超分辨率算法,实现从低清到高清的有效转换。

pp12345的博客 429

【UV打印机】RYPC打印软件教程(二)-软件界面概述

下图是控制软件的主操作界面.将喷绘机的操作规纳为四块,分别为参数设置,任务选择,打印控制,系统维护,对于日常打印而言,只需操作任务选择,打印控制。从而使汲及的操作相对较少,使得系统对普通用户而言简单易用.

Print World的专栏 3601

NS3中TypeId详解

在ns-3仿真框架中,TypeId是类型信息管理系统,用于注册、继承、动态创建对象,并提供属性系统回调机制。

weixin_45817507的博客 854

VS2022 中 std::mutex 静态初始化陷阱:一次诡异崩溃的排查记录

VS2022中使用std::mutex时遇到的静态初始化陷阱问题。该问题源于VS2022 17.4版本为std::mutex添加constexpr支持后,全局静态初始化可能导致系统资源未就绪时锁失效或崩溃。文章分析了问题现象、影响范围,并提供了解决方案。最后给出了排查清单和核心建议

qq_34552942的博客 952

C++ typeid详解

C++为我们提供了一种可以判断变量类型的关键字,即typeid,它的参数和sizeof一样,可以是一个变量,或者一种类型。typeid的返回值是type_info类,而且返回的是一个左值。type_info类禁用了拷贝构造函数,因此我们必须要用引用或指针来存储结果,如: const type_info& type1=typeid(int); const type_info* type2=&typeid(int); name() 作用:返回描述变量类型的字符串(注意:是类型全名)。 基本用法

[PE]经典八炮的博客 9233

carsim与simulink联合仿真学习笔记(二)——使用C-class车模做driver model仿真(5 driver sensors)

Driver model 在carsim的Simulink库中自带外部驾驶员模型,打开后如图所示: 然后打开carsim中对应的数据集,如图所示: 具体仿真步骤不在赘述,注意到这里选择的是E-Class车模,那么如果我想选择C-Class车型进行仿真呢?点三角选择车型可以看到: 马赛克部分是我后来建的,如过没有使用过是没有马赛克部分的。那么既然这里没有C-class,又该怎么办呢? 创建C-...

xufuqiang2017的博客 4117

433MHz无线通信避坑指南:如何解决信号干扰和误码问题

本文深入探讨433MHz无线通信中的信号干扰和误码问题,提供从射频前端设计到协议优化的全链路解决方案。通过天线匹配、电源噪声抑制、曼彻斯特编码改进及实时频点切换等技术,显著提升通信稳定性和距离。适合智能家居和工业无线控制系统的开发者参考。

weixin_29288313的博客 417
上一篇: C++11中unique_ptr的使用
下一篇: FileZilla Server源码分析
TuxedoLinux
博客等级 码龄9年 268粉丝 34原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值