typeid详解

From: http://www.cppblog.com/smagle/archive/2010/05/14/115286.aspx

 

   在揭开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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H5静态页面跳转微信小程序;从外部浏览器,点击H5链接跳转打开微信小程序;以及在微信内直接点击H5链接打开微信小程序;

参考链接 需求&#xff1a;从外部浏览器&#xff0c;点击H5链接跳转打开微信小程序&#xff1b;以及在微信内直接点击H5链接打开微信小程序&#xff1b; 步骤1&#xff1a; 小程序开发需要使用云开发创建项目&#xff0c;使用云开发生成的项目会自带云函数文件夹&#xff1b;…

c简单的链表错误及改正

2019独角兽企业重金招聘Python工程师标准>>> 以下代码运行时崩溃&#xff1a; #include <iostream> using namespace std; struct node { int num; struct node * next; }; node * creat() { node * headNULL;node*HEADhead; cout<<"输入数字&…

uni-app微信小程序跳转公众号;微信小程序打开公众号;微信小程序识别二维码添加好友;微信小程序通过公众号添加好友;小程序里识别企业微信二维码点击联系人名片无反应?

需求&#xff1a; 在微信小程序页面中&#xff0c;长按识别图片二维码&#xff0c;识别出联系人后&#xff0c;点击添加好友&#xff1b; 问题&#xff1a;微信官方社区说是小程序添加不了好友&#xff1b; 解决方案&#xff1a; 目前只能通过微信小程序跳转至公众号&#xf…

A*算法入门

From: http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前&#xff0c;先介绍几个理论知识&#xff0c;有助于理解A*算法。 启发式搜索&#xff1a;启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估&#xff0c;得到最好的位置&a…

ThinkPHP讲解(一)框架基础

ThinkPHP框架知识点过于杂乱&#xff0c;接下来将以问题的形势讲解tp&#xff08;ThinkPHP的简写&#xff09; 1.tp框架是什么&#xff0c;为什么使用是它&#xff1f; 一堆代码的集合&#xff0c;里边有变量、函数、类、常量&#xff0c;里边也有许多设计模式MVC、AR数据库、单…

uni-app文档需要注意细节点

1.非H5端&#xff0c;不能使用浏览器自带对象&#xff0c;比如document、window、localstorage、cookie等&#xff0c;更不能使用jquery等依赖这些浏览器对象的框架。因为各家小程序快应用都不支持这些对象。 2.APP 和小程序的导航栏和 tabbar 均是原生控件&#xff0c;元素区…

VMware里装XP 没有找到硬盘驱动器

遇到问题&#xff1a;解决&#xff1a;要给虚拟机配上一个虚拟的硬盘驱动器。在VMWare的虚拟机配置里面给这个虚拟机增加硬盘&#xff0c;选IDE模式&#xff0c;而非SCSI&#xff0c;设定硬盘大小和文件名就可以了。转载于:https://www.cnblogs.com/haxianhe/p/9271196.html

serv-u无法自动启动:无法开始服务器!服务器执行缺少

我在服务器上安装了一个serv-u 6.3版本&#xff0c;安装的时候一切正常。安装后想设置为自动开设&#xff08;系统服务&#xff09;勾打上时候&#xff0c;开设报错。在服务里面查看&#xff0c;发现servu的服务器没有起来&#xff0c;手动启动也不行。网上查了很多方法&#x…

uni-app微信小程序登录;uni-app微信登录小程序;uni-app微信登录app;

思路&#xff1a; 通过uni-app文档可知:实现微信登录&#xff0c;无论是app还是小程序&#xff0c;都需要唯一标识openid&#xff0c;然后通过openid取掉后端的登录接口&#xff0c;获取cookie然后做登录跳转&#xff1b; 【-【-【必须先调用微信的登录接口uni.login&#xff0…

线性表 - 数据结构和算法06

线性表 让编程改变世界 Change the world by program 感受线性表的存在 各位鱼油大家好&#xff0c;从今天开始小甲鱼带大家开始学习第一个数据结构&#xff1a;线性表 先让我我们通过图片来感受一下&#xff0c;线性表的特性吧。 [caption id"attachment_758" a…

uni-app微信小程序获取手机号;微信小程序获取手机号,获取到后需要进行解密;微信小程序获取手机号失败 Error:该appId没有权限

方法1.uni-app登录加获取手机号解密—直接看此篇即可解决 微信小程序获取手机号注意点&#xff1a; 1.需要先登录&#xff0c;微信小程序登录看这篇 2.手机号获取到时加密的&#xff0c;需要后端解密或者前端自己解密&#xff08;解密时候就会用到登录得到的session_key&#…

Swift 3.0 on Ubuntu 15.10

一、安装swift 3.0 1. 下载 https://swift.org/download/ 找到swift-3.0 ubuntu 15.10版本下载&#xff1a; https://swift.org/builds/swift-3.0-preview-1/ubuntu1510/swift-3.0-preview-1/swift-3.0-preview-1-ubuntu15.10.tar.gz 2. 解压文件&#xff0c;然后移动改名到/op…

解决uni-app官方弹框popup关闭不了问题;/pages/extUI/popup/popup;uni-app弹框popup打开调用事件。unin-app弹框封装;

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210716165216781.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2lfYW1fYV9kaXY,size_16,color_FFFFFF,t_70)官方uni-app的弹框popup模板问题: 官方的弹框示…

uni-app自定义tabBar;uni-app小程序自定义tabBar;uni-app小程序修改中间tabBar导航栏大小;uni-app中间导航栏凸起;uni-app修改底部导航栏

需求&#xff1a;要求小程序&#xff0c;中间的tabBar自定义凸起或者图标变大&#xff1b; 问题&#xff1a;查看uni-app的tabBar文档可知&#xff0c;小程序是不支持midButton的&#xff1b; 解决思路&#xff1a;隐藏uni-app原有的tabBar&#xff0c;然后换成自己手写的导航…

uni-app小程序 点击页面滚动到指定位置

uni.pageScrollTo({scrollTop: 0,duration: 300,})

mysql Connector C/C++ 多线程封装

From: http://blog.csdn.net/educast/article/details/14163519 在网上找了好久&#xff0c;有很多封装&#xff0c;但是感觉对多线程处理的不多&#xff0c;都不是很理想。封装完的第一个版本&#xff0c;想法比较简单&#xff0c;使用一个单例模式&#xff0c;对应一个连接&a…

uni-app微信小程序image引入图片;background-image背景图引入图片;小程序预览本地图片;小程序图片过大引入报错;获取本地图片的网络地址;

uni-app小程序图片使用有image标签和background-image背景图两种方式&#xff1a; 下有获取本地图片的网络地址方式&#xff1a;见第四步 一、方式一&#xff1a;使用image标签引入&#xff1a; uni-app官方image 1.官方文档说&#xff1a;src 仅支持相对路径、绝对路径&…

微商小程序加人加粉推广平台二维码

微商加人推广平台丨微商加粉推广平台丨微商拼团丨微商产品推广。

JS node 后端签名前端文件直传ali-oss解决方案

1&#xff1a;首先打开跨域 上面搞好了开始写代码 html <input type"file" id"upload" onchange"uploadfile()"> js function uploadfile() {var file document.getElementById(upload).files[0]$.ajax({url: /policy,data: ,type: get…