RTTI(Run-TimeType Information, 运行时类型信息),它提供了运行时确定对象类型的方法。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。

The typeid operator provides a program with the ability to retrieve the actual derived type of the object referred to by a pointer or a reference. The typeid operator requires run time type information (RTTI) to be generated, which must be explicitly specified at compile time through a compiler option. The typeid operator returns an lvalue of type const std::type_info that represents the type of expression expr.

typeid是C++的一个关键字,等同于sizeof这类操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用。type_info的name成员函数返回C-style的字符串。

如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。

使用typeid时应注意:

(1)、typeid运算符允许在运行时确定对象的类型;

(2)、typeid的结果是const type_info&;

(3)、typeid运算符在应用于多态类类型的左值时执行运行时检查,其中对象的实际类型不能由提供的静态信息确定;

(4)、typeid也可在模板中使用以确定模板参数的类型;

(5)、typeid是操作符,不是函数,运行时获知变量类型名称;

(6)、要使用typeid,首先要确保编译器开启了运行时类型检查(RTTI)。

以下是测试代码:

#include "typeid.hpp"
#include <assert.h>
#include <iostream>
#include <string>
#include <typeinfo>
#include <vector>int func(int a)
{return 0;
}typedef int(*func_ptr)(int);
class Base { public: Base(){} };int test_typeid1()
{char char_ = 'a';unsigned char uchar_ = 'b';short short_ = 2;unsigned short ushort_ = 3;int int_ = 1;unsigned int uint_ = 4;float float_ = 2.0;double double_ = 1.0;long long_ = 5;long long llong_ = 6;int array[10] = { 1};int* array_header = array;std::string string_;std::vector<int> int_vector;func_ptr f = func;Base Base_;Base* pBase_ = new Base;Base& Base__ = Base_;// 对于返回字符串的具体内容,与编译器有关std::cout << "char_ type: " << typeid(char_).name() << std::endl; // char_ type: charassert(typeid(char).name() == typeid(char_).name());std::cout << "uchar type: " << typeid(uchar_).name() << std::endl; // uchar type: unsigned charassert(typeid(unsigned char).name() == typeid(uchar_).name());std::cout << "short_ type: " << typeid(short_).name() << std::endl; // short_ type: shortassert(typeid(short).name() == typeid(short_).name());std::cout << "ushort_ type: " << typeid(ushort_).name() << std::endl; // ushort_ type: unsigned shortassert(typeid(unsigned short).name() == typeid(ushort_).name());std::cout << "int_ type: " << typeid(int_).name() << std::endl; // int_ type: intassert(typeid(int).name() == typeid(int_).name());std::cout << "uint_ type: " << typeid(uint_).name() << std::endl; // uint_ type: unsigned intassert(typeid(unsigned int).name() == typeid(uint_).name());std::cout << "float_ type: " << typeid(float_).name() << std::endl; // float_ type: floatassert(typeid(float).name() == typeid(float_).name());std::cout << "double_ type: " << typeid(double_).name() << std::endl; // double_ type: doubleassert(typeid(double).name() == typeid(double_).name());std::cout << "long_ type: " << typeid(long_).name() << std::endl; // long_ type: longassert(typeid(long).name() == typeid(long_).name());std::cout << "llong_ type: " << typeid(llong_).name() << std::endl; // llong_ type: __int64assert(typeid(long long).name() == typeid(llong_).name());std::cout << "array[] type: " << typeid(array).name() << std::endl; // array[] type: int [10]assert(typeid(int [10]).name() == typeid(array).name());std::cout << "array_header type: " << typeid(array_header).name() << std::endl; // array_header type: int * __ptr64assert(typeid(int*).name() == typeid(array_header).name());std::cout << "string_ type: " << typeid(string_).name() << std::endl; // string_ type: class std::basic_string<char,struct std::char_traits<char>, class std::allocator<char>>assert(typeid(std::string).name() == typeid(string_).name());std::cout << "int_vector type: " << typeid(int_vector).name() << std::endl; // int_vector type: class std::vector<int,class std::allocator<int>>assert(typeid(std::vector<int>).name() == typeid(int_vector).name());std::cout << "f type: " << typeid(f).name() << std::endl; // f type : int(__cdecl*)(int)assert(typeid(int(*)(int)).name() == typeid(f).name());std::cout << "Base_ type: " << typeid(Base_).name() << std::endl; // Base_ type: class Baseassert(typeid(class Base).name() == typeid(Base_).name());std::cout << "pBase_ type: " << typeid(pBase_).name() << std::endl; // pBase_ type: class Base * __ptr64assert(typeid(class Base*).name() == typeid(pBase_).name());std::cout << "Base__ type: " << typeid(Base__).name() << std::endl; // Base__ type: class Baseassert(typeid(class Base).name() == typeid(Base__).name());delete pBase_;return 0;
}// reference: http://en.cppreference.com/w/cpp/language/typeid
int test_typeid2()
{struct Base {}; // non-polymorphicstruct Derived : Base {};struct Base2 { virtual void foo() {} }; // polymorphicstruct Derived2 : Base2 {};int myint = 50;std::string mystr = "string";double *mydoubleptr = nullptr;std::cout << "myint has type: " << typeid(myint).name() << '\n' // myint has type: int<< "mystr has type: " << typeid(mystr).name() << '\n' // mystr has type: class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>><< "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n'; // mydoubleptr has type: double * __ptr64// std::cout << myint is a glvalue expression of polymorphic type; it is evaluatedconst std::type_info& r1 = typeid(std::cout << myint); // 50std::cout << "std::cout<<myint has type : " << r1.name() << '\n'; // std::cout<<myint has type: class std::basic_ostream<char, struct std::char_traits<char>>// std::printf() is not a glvalue expression of polymorphic type; NOT evaluatedconst std::type_info& r2 = typeid(std::printf("%d\n", myint));std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n'; // printf(\"%d\\n\",myint) has type : int// Non-polymorphic lvalue is a static typeDerived d1;Base& b1 = d1;std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n'; // reference to non-polymorphic base: struct 'int __cdecl test_typeid2(void)'::'2'::BaseDerived2 d2;Base2& b2 = d2;std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n'; // reference to polymorphic base: struct 'int __cdecl test_typeid2(void)'::'3'::Derived2try {// dereferencing a null pointer: okay for a non-polymoprhic expressionstd::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; // mydoubleptr points to double// dereferencing a null pointer: not okay for a polymorphic lvalueDerived2* bad_ptr = NULL;std::cout << "bad_ptr points to...";  // bad_ptr points to... std::cout << typeid(*bad_ptr).name() << '\n';}catch (const std::bad_typeid& e) {std::cout << " caught " << e.what() << '\n'; // caught Attempted a typeid of NULL pointer!}return 0;
}///
// reference: https://msdn.microsoft.com/zh-cn/library/fyf39xec.aspx
template < typename T >
T max(T arg1, T arg2) {std::cout << typeid(T).name() << "s compared." << std::endl;return (arg1 > arg2 ? arg1 : arg2);
}int test_typeid3()
{class Base {public:virtual void vvfunc() {}};class Derived : public Base {};Derived* pd = new Derived;Base* pb = pd;std::cout << typeid(pb).name() << std::endl;   //prints "class Base *" // class 'int __cdecl test_typeid3(void)'::'2'::Base * __ptr64std::cout << typeid(*pb).name() << std::endl;   //prints "class Derived" // class 'int __cdecl test_typeid3(void)'::'2'::Derivedstd::cout << typeid(pd).name() << std::endl;   //prints "class Derived *" // class 'int __cdecl test_typeid3(void)'::'2'::Derived * __ptr64std::cout << typeid(*pd).name() << std::endl;   //prints "class Derived" // class 'int __cdecl test_typeid3(void)'::'2'::Deriveddelete pd;float a = 1.2, b = 3.4;max(a, b); // floats comparedreturn 0;
}

GitHub: https://github.com/fengbingchun/Messy_Test

C++中typeid的使用相关推荐

  1. 关于C++中typeid().name()输出数据类型为m、h 的解释

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一 ...

  2. C++中typeid的用法

    typeid是C++的关键字之一,等同于sizeof这类的操作符.typeid操作符的返回结果是名为type_info的标准库类型的对象的引用. 如果表达式的类型是类类型且至少包含有一个虚函数,则ty ...

  3. 深入理解C++中五种强制类型转换的使用场景

    深入理解C++中五种强制类型转换的使用场景 1.C风格的强制类型转换 2.C++风格的强制类型转换 2.1.static_cast 2.1.1.用于基本内置数据类型之间的转换 2.1.2.用于指针之间 ...

  4. GNU Make 使用手册(于凤昌中译版)

    GNU Make 使用手册(中译版) 翻译:于凤昌 GNU make Version 3.79 April 2000 Richard M. Stallman and Roland McGrath 1 ...

  5. AOP通过开启注解方式自动注入值

    注解:EnableDimEnhance package com.comma.teeth.enhance.dim.annotation;import java.lang.annotation.Docum ...

  6. C++11 类型推导decltype

    我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行.RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通 ...

  7. django ForeignKey的使用

    ForeignKey,ManyToManyField与OneToOneField分别在Model中定义多对一,多对多,一对一关系. ForeignKey 加入数据库中要建立两张表,userlist和U ...

  8. C++基础::函数、类、类型所在的头文件 接口的介绍

    除非特别说明,所在的命名空间均是:标准命名空间,也即std: stuff header 说明 ifstream ofstream fstream <fstream> 文件流 in>& ...

  9. 基于 SpringBoot 的个人博客系统设计与实现(含论文与程序代码).rar

    绪论 1 1.1系统的概述1 1.2系统的研究背景 2需求分析 2.1系统需求分析 2.2可行性分析 2.2.1技术可行性 2.2.2经济可行性 2.2.3操作可行性 2.3开发及运行环境 3总体设计 ...

最新文章

  1. linux下find,xargs命令详解和实例
  2. Xamarin Android教程Android基本知识版本介绍与系统介绍
  3. Git+SourceTree使用时出现的问题
  4. CRM客户关系管理系统(十三)
  5. H - Tunnel Warfare HDU - 1540
  6. 程序员面试金典 - 面试题 17.16. 理发师(动态规划DP)
  7. 序列推荐系统文献调研(1)
  8. arp 不同网段 相同vlan_同vlan不同网段能否ping通?
  9. 钉钉打卡如何破译人脸识别_疫情常态下,如何选择合适的考勤管理系统和考勤打卡工具?...
  10. Oracle 常用符号CHR
  11. javascript中闭包的真正作用
  12. 陈纪修老师《数学分析》 第07章:定积分 笔记
  13. 不学点《近世代数》怎么学好现代密码学
  14. 计算机控制器的简写,工业控制常用英语及缩写
  15. MCS-51单片机的外部引脚及片外总线
  16. vue项目PC端如何适配不同分辨率屏幕
  17. 计算机导师问读研计划和后续计划,考研面试,问“研究生时期的规划”怎么回答急...
  18. 太阳辐射最少的地区_读中国年太阳辐射总量分布图,寻找年太阳辐射量最多和最少的地方...
  19. 量化投资_期货日内交易的波动率思考
  20. 随笔记录——numpy4(伪随机数生成)

热门文章

  1. 高大上的调音台,一秒变成调音师!
  2. js jquery 获取元素(父节点,子节点,兄弟节点),元素筛选
  3. (翻译)Understanding Convolutional Neural Networks for NLP
  4. 刘强东终于向自己的兄弟下手了!
  5. 学习笔记:Java大数据培训学校全套教程-JavaScript基础(20)
  6. java中 else if用法_java if else 用法
  7. 【华为OD机试真题 python】特异性双端队列 | 最小调整顺序次数【2022 Q4 | 100分】
  8. android和苹果内存,安卓的8G运行内存为什么与苹果3G的运行内存不能抗衡?
  9. 微信公众账号的订阅号与服务号有什么区别?
  10. 阿里云服务器配置(一)基础