首页 > 编程语言 >C++ typeid关键字详解

C++ typeid关键字详解

时间:2023-06-19 17:44:47浏览次数:52  
标签:info typeid const C++ __ 详解 base type

typeid关键字

 

注意:typeid是操作符,不是函数。这点与sizeof类似)

运行时获知变量类型名称,可以使用 typeid(变量).name()

需要注意不是所有编译器都输出”int”、”float”等之类的名称,对于这类的编译器可以这样使用

int ia = 3;

if(typeid(ia) == typeid(int))

{

    cout <<"int" <<endl;

}

RTTI(Run-Time Type Identification)-运行时类型识别

 

在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。

在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid

  • dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。
  • typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义,稍后我们看一下vs和gcc库里面的源码),它的表达式有下图两种形式。

实现机制与使用技巧

 

type_info类对象类别判别

 

对象类别判别分析

 

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

否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。

ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作(在之后的章节中我会来分析type_info类文件的源码)

运算

描述

t1 == t2

如果两个对象t1和t2类型相同,则返回true;否则返回false

t1 != t2

如果两个对象t1和t2类型不同,则返回true;否则返回false

t.name()

返回类型的C-style字符串,类型名字用系统相关的方法产生1

t1.before(t2)

返回指出t1是否出现在t2之前的bool值

type_info类提供了public虚 析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符(由此可见,如果把typeid看作函数的话,其应该是type_info的 友元)。type_info的name成员函数返回C-style的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这具体由编译器的实现所决定的,标准只要求实现为每个类型返回唯一的字符串。

type_info类源代码

 

使用sudo find / -name typeinfo.h来查找源码 

 

#ifndef _TYPEINFO

#define _TYPEINFO

 

#include <exception>

 

namespace std 

{

 

  class type_info 

  {

  public:

 

    virtual ~type_info();

    { return __name[0] == '*' ? __name + 1 : __name; }

 

 

    bool before(const type_info& __arg) const

    { return __name < __arg.__name; }

 

    bool operator==(const type_info& __arg) const

    { return __name == __arg.__name; }

 

    bool operator!=(const type_info& __arg) const

    { return !operator==(__arg); }

 

    virtual bool __is_pointer_p() const;

 

    virtual bool __is_function_p() const;

 

  protected:

    const char *__name;

 

    explicit type_info(const char *__n): __name(__n) { }

 

  private:

    type_info& operator=(const type_info&);

    type_info(const type_info&);

  };

 

} // extern "C++"

#endif

示例1-基本数据类型

 

下表列出了使用typeid操作符的表达式的值

int a;

double b;

char * c;

long d;

运算

描述

typeid(a) == typeid(int)

true

typeid(a) == typeid(float)

false

typeid(a) == typeid(int *)

false

typeid(b) == typeid(double)

true

typeid(b) == typeid(float)

false

typeid(b) == typeid(long double)

false

typeid(c) == typeid(char *)

true

typeid(c) == typeid(char)

false

typeid(c) == typeid(string)

false

typeid(d) == typeid(long)

true

typeid(d) == typeid(int)

false

操作符typeid返回的是一个type_info类(用于描述数据类型的一个系统类)对象的引用。这个操作符可以用于表达式和类型名(包括自定的数据类型,比如类)。

示例2-类对象

 

class base

{

public :

    void m(){cout<<"base"<<endl;}

};

class derived : public base

{

public:

    void m(){cout<<"derived"<<endl;}

};

假设我们根据例2中定义的两个类来定义如下指针:

base * p = new derived;

  •  

下表将给出使用typeid操作符的结果。

运算

描述

typeid(p) == typeid(base*)

true

typeid(p) == typeid(derived*)

false

typeid(*p) == typeid(base)

true

typeid(*p) == typeid(derived)

false

对于表达式typeid(p),同样,因为p是base*类型的指针,因此typeid(p) == typeid(base*)为真,而typeid(p) == typeid(derived*)为假。而对于表达式typeid(*p),由于此时的基类不具有多态性,因而*p将会采用编译期类型来计算,编译期*p是base对象,因此表达式typeid(*p) == typeid(derived)为假,typeid(*p) == typeid(base)为真。

示例3-带虚函数的基类

 

class base

{

public :

    virtual void m(){cout<<"base"<<endl;}

};

class derived : public base

{

public:

    void m(){cout<<"derived"<<endl;}

};

假设我们如本例所示定义了两个类base类和derived类,基于这两个类定义,我们定义指针如下:

base * p = new derived;

下表将给出使用typeid操作符的结果。

运算

描述

typeid(p) == typeid(base*)

true

typeid(p) == typeid(derived*)

false

typeid(*p) == typeid(base)

false

typeid(*p) == typeid(derived)

true

对于表达式typeid(p),因为p是base*类型的指针,因此typeid(p) == typeid(base*)为真,而typeid(p) == typeid(derived*)为假。而对于表达式typeid(*p),因为base类具有多态性,因而在计算typeid(*p)时会根据运行时p所指向的实际类型去计算,而本例中p指向的是派生类对象,因此表达式typeid(*p) == typeid(derived)为真,typeid(*p) == typeid(base)为假。

异常处理bad_typeid

 

  class bad_typeid : public exception 

  {

  public:

    bad_typeid () throw() { }

 

    // This declaration is not useless:

    // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118

    virtual ~bad_typeid() throw();

 

    // See comment in eh_exception.cc.

    virtual const char* what() const throw();

  };

} // namespace std

 

参照

【C++】typeinfo.h

C++中的typeid关键字

 原文:https://blog.csdn.net/gatieme/article/details/50947821

 

https://blog.csdn.net/yuhan61659/article/details/81557662

 

标签:info,typeid,const,C++,__,详解,base,type
From: https://www.cnblogs.com/im18620660608/p/17491741.html

相关文章

  • C++11:Lambda表达式
    Lambda表达式为了一些简单的函数直接调用封装[var]:表示值传递方式捕捉变量var[=]:表示值传递捕捉所有父作用域中的变量(包括成员函数中的this)[&var]:表示引用传递捕捉变量var[&]:表示引用传递捕捉所有父作用域中的变量(包括成员函数中的this)[this]:表示值传递方式捕捉当前的this指......
  • Rockchip rk3588 U-Boot详解 (三)
    Rockchiprk3588U-Boot详解(三)专栏总目录1.1Environment-VariablesENV(Environment-Variables)是U-Boot支持的一种全局数据管理和传递方式,原理是构建一张HASH映射表,把用户的数据以"键值-数据"作为表项进行管理。EVN通常用于定义平台配置参数:固件加载地址、网络配置(ipaddr、serve......
  • static详解
     static+属性 //静态属性 ,可直接通过类调用publicstaticstringname=“张三”static+方法 // 静态方法,可直接通过类调用publicstaticvoidadd(){system.out.print("xxxxxx")}static+{} //静态模块代码,最先执行且只执行一次static{system.out.print("xxxxx......
  • (转)kubernetes(k8s) yaml 文件详解2
    原文:https://juejin.cn/post/7202145223014252602#heading-0一、K8S支持的文件格式kubernetes支持YAML和JSON文件格式管理资源对象。JSON格式:主要用于api接口之间消息的传递YAML格式:用于配置和管理,YAML是一种简洁的非标记性语言,内容格式人性化,较易读1、yaml和json的主要区......
  • UE5 C++ 定时器使用
    概念定时器在全局定时器管理器(FTimerManager类型)中管理。全局定时器管理器存在于游戏实例对象上以及每个场景中。有两个函数可以使用定时器管理器来设置定时器:SetTimer和SetTimerForNextTick,它们各自都有一些重载,每个函数都可以连接到任意类型的对象或函数委托使用访......
  • 【实例】深入详解 CSS 中的 object-fit 5个属性值
    【实例】深入详解CSS中的object-fit5个属性值在本文中,我们将介绍如何使用object-fit,以及一些实际用例和建议。我们并不总是能够为HTML元素加载不同大小的图像,如果我们使用与图像纵横比不成比例的宽度和高度,则图像可能会被压缩或拉伸。为解决此问题,我们可以为img元素使用ob......
  • vi命令使用详解
    vi命令使用详解1.三种工作模式命令模式:通过命令对文件进行常规操作打开文件时进入命令模式(vi的入口)通过命令对文件进行常规操作,如定位、翻页、复制、粘贴、删除等在图形界面下通过鼠标或快捷键实现的的操作末行模式:执行保存、退出等操作若要退出vi返回控制台,需在末......
  • OnTriggerEnter与OnCollisionEnter详解
    1,测试OnTriggerEnter和OnCollisionEnter的区别测试:如果两个物体A,B两者都有碰撞体collider(BoxCollider,SphereCollider,CapsuleCollider等)A,B都有刚体(Rigidbody)A或者B中有一个勾选isTrigger或者两者都勾选isTriggerA和B都可以进入OnTriggerEnter方法,但是不可进入OnCollisio......
  • C++ 重载运算符
    为了叙述的方便,以下内容以赋值运算符为例赋值运算符本质是一个名为operator=的函数,某些运算符必须定义为成员函数赋值运算符定义示例代码classFoo{public:Foo&operator=(constFoo&);};......
  • C++多态的原理(虚函数指针和虚函数表) --imxiangzi 好好看
     C++多态的原理(虚函数指针和虚函数表)1.虚函数指针和虚函数表2.继承中的虚函数表2.1单继承中的虚函数表2.2多继承中的虚函数表3.多态的原理4.总结1.虚函数指针和虚函数表以下代码:问类实例化出的对象占几个字节?#include<iostream>usingnamespacestd;classA{ intm_a;publi......