C++<第三十一篇>:typeid运算符

typeid 运算符是用来获取一个表达式的类型信息。
类型信息对于编程语言非常重要,它描述了数据的各种属性。
对于基本类型(int、float 等等)的数据类型信息所包含的内容比较简单,主要是指数据的类型。
对于类类型的数据(也就是对象),类型信息是指对象所属的类、所包含的成员、所在的继承关系等。
类型信息是创建数据的模板,数据占用多大内存,能进行什么样的操作、该如何操作等,这些都由它的类型信息决定。

(1)typeid 的定义

const type_info& type_info变量 = typeid(类型或表达式);

typeid 是一个标准库 typeinfo 中的函数,所以需要添加如下代码:

#include <typeinfo>

就拿获取普通数据类型来举例:

    int a = 10;
    const type_info& mInfo = typeid(a);
    cout << mInfo.name() << endl; // 获取类型的名称
    cout << mInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo.hash_code() << endl; // 获取类型对象的hash code

输出结果是:

int
.H
12638232278978672507

typeid 的使用非常灵活,它的操作数可以是普通变量、对象、内置类型(int、float等)、自定义类型(结构体和类),还可以是一个表达式。

type_info 类的几个成员函数,下面是对它们的介绍:

  • name() 用来返回类型的名称。
  • raw_name() 用来返回名字编码(Name Mangling)算法产生的新名称。
  • hash_code() 用来返回当前类型对应的 hash 值。hash 值是一个可以用来标志当前类型的整数,有点类似学生的学号、公民的身份证号、银行卡号等。不过 hash 值有赖于编译器的实现,在不同的编译器下可能会有不同的整数,但它们都能唯一地标识某个类型。

(2)type_info 成员函数介绍

size_t hash_code() const;
返回一个类的hash code,它是类的唯一标志。

const char* name() const;
返回一个能表示类型名称的字符串。
但是C++标准并没有规定这个字符串是什么形式的,例如对于上面的objInfo.name()语句,VC/VS 下返回“class Base”,但 GCC 下返回“4Base”。

const char* raw_name() const;
返回名字编码(Name Mangling)算法产生的新名称。

bool before (const type_info& rhs) const;
判断一个类型是否位于另一个类型的前面,rhs 参数是一个 type_info 对象的引用。
但是C++标准并没有规定类型的排列顺序,不同的编译器有不同的排列规则,程序员也可以自定义。要特别注意的是,这个排列顺序和继承顺序没有关系,基类并不一定位于派生类的前面。

bool operator== (const type_info& rhs) const;
重载运算符“==”,判断两个类型是否相同,rhs 参数是一个 type_info 对象的引用。

bool operator!= (const type_info& rhs) const;
重载运算符“!=”,判断两个类型是否不同,rhs 参数是一个 type_info 对象的引用。

(3)typeid支持哪些数据类型

typeid 支持 基本数据类型类类型

演示代码如下:

    int a = 10;
    const type_info& mInfo1 = typeid(a); // 整型变量
    cout << mInfo1.name() << endl; // 获取类型的名称
    cout << mInfo1.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo1.hash_code() << endl; // 获取类型对象的hash code

    const type_info& mInfo2 = typeid(int); // 整数类型
    cout << mInfo2.name() << endl; // 获取类型的名称
    cout << mInfo2.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo2.hash_code() << endl; // 获取类型对象的hash code

    float b = 10.1f;
    const type_info& mInfo3 = typeid(b); // 浮点型变量
    cout << mInfo3.name() << endl; // 获取类型的名称
    cout << mInfo3.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo3.hash_code() << endl; // 获取类型对象的hash code

    D d;
    const type_info& mInfo4 = typeid(d); // 普通类对象
    cout << mInfo4.name() << endl; // 获取类型的名称
    cout << mInfo4.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo4.hash_code() << endl; // 获取类型对象的hash code

    const type_info& mInfo5 = typeid(D); // 类类型
    cout << mInfo5.name() << endl; // 获取类型的名称
    cout << mInfo5.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo5.hash_code() << endl; // 获取类型对象的hash code

    const type_info& mInfo6 = typeid(struct STU); // 结构体类型
    cout << mInfo6.name() << endl; // 获取类型的名称
    cout << mInfo6.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo6.hash_code() << endl; // 获取类型对象的hash code

    const type_info& mInfo7 = typeid(1 + 2 + 3 + 4); // 表达式
    cout << mInfo7.name() << endl; // 获取类型的名称
    cout << mInfo7.raw_name() << endl; // 获取名字算法产生的新名称
    cout << mInfo7.hash_code() << endl; // 获取类型对象的hash code

(4)判断类型是否是同一类型

决定两者是否相等取决于:不仅hash code要一样,而且值也需要一样。

typeid 运算符只能判断两者之间的类型是否一致,它不能判断两者是否相等。

【基本数据类型举例】

    int a = 10;
    const type_info& aInfo = typeid(a); // 整型变量
    cout << aInfo.name() << endl; // 获取类型的名称
    cout << aInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << aInfo.hash_code() << endl; // 获取类型对象的hash code

    int b = 11;
    const type_info& bInfo = typeid(b); // 整型变量
    cout << bInfo.name() << endl; // 获取类型的名称
    cout << bInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << bInfo.hash_code() << endl; // 获取类型对象的hash code

    const type_info& intInfo = typeid(int); // 整数类型
    cout << intInfo.name() << endl; // 获取类型的名称
    cout << intInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << intInfo.hash_code() << endl; // 获取类型对象的hash code

    bool isEqual1 = aInfo.operator==(bInfo);
    cout << isEqual1 << endl;
    
    bool isEqual2 = aInfo.operator==(intInfo);
    cout << isEqual2 << endl;

    bool isEqual3 = intInfo.operator==(bInfo);
    cout << isEqual3 << endl;

代码是基本数据类型a和b,以及int比较,输出结果是:

int
.H
12638232278978672507
int
.H
12638232278978672507
int
.H
12638232278978672507
1
1
1

我们发现,aInfo、bInfo、intInfo 三者的hash code一致,并且 operator== 函数的返回值为1,1表示相等。

如果是int数据和float数据比较呢?

    int a = 10;
    const type_info& aInfo = typeid(a); // 整型变量
    cout << aInfo.name() << endl; // 获取类型的名称
    cout << aInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << aInfo.hash_code() << endl; // 获取类型对象的hash code

    float b = 11.1f;
    const type_info& bInfo = typeid(b); // 浮点变量
    cout << bInfo.name() << endl; // 获取类型的名称
    cout << bInfo.raw_name() << endl; // 获取名字算法产生的新名称
    cout << bInfo.hash_code() << endl; // 获取类型对象的hash code

    bool isEqual1 = aInfo.operator==(bInfo);
    cout << isEqual1 << endl;

输出结果是:

int
.H
12638232278978672507
float
.M
12638226781420530164
0

两者hash code不同,并且 operator== 函数的返回值为0,0表示不相等。

【类类型举例】

    D d1;
    const type_info& aInfo = typeid(d1);
    cout << aInfo.name() << endl;
    cout << aInfo.raw_name() << endl;
    cout << aInfo.hash_code() << endl;

    const type_info& bInfo = typeid(D);
    cout << bInfo.name() << endl;
    cout << bInfo.raw_name() << endl;
    cout << bInfo.hash_code() << endl;

    bool isEqual = aInfo.operator==(bInfo);
    cout << isEqual << endl;

输出结果是:

class D
.?AVD@@
5621110339268995829
class D
.?AVD@@
5621110339268995829

1

operator== 函数的返回值为1,1表示相等。

    D* d1 = new D();
    D* d2 = new D();
    const type_info& aInfo = typeid(*d1);
    cout << aInfo.name() << endl;
    cout << aInfo.raw_name() << endl;
    cout << aInfo.hash_code() << endl;

    const type_info& bInfo = typeid(*d2);
    cout << bInfo.name() << endl;
    cout << bInfo.raw_name() << endl;
    cout << bInfo.hash_code() << endl;

    bool isEqual = aInfo.operator==(bInfo);
    cout << isEqual << endl;

输出结果是:

class D
.?AVD@@
5621110339268995829
class D
.?AVD@@
5621110339268995829

1

operator== 函数的返回值也为1,1表示相等。

通过以上举例,已经可以充分证明:typeid 运算符只能判断两者之间的类型是否一致,它不能判断两者是否相等。

(5)判断是否是某个类型

程序设计中,typeid运算符常常用来判断都对象是否是某个类型。

演示代码如下:

#include <iostream>
#include <typeinfo>

using namespace std;

class D 
{
public:
    void display()
    {
        cout << "我的类型是D" << endl;
    }
};

template <class T>
class MyTemplate
{
    T t;

public:
    MyTemplate(T tt)
    {
        t = tt;
    }
    void display()
    {
        const type_info& typeInfo = typeid(D);
        if (typeInfo.operator==(typeid(t))) 
        {
            D d;
            d.display();
        }
        else
        {
            cout << "我的类型不是D" << endl;
        }
    }
};

int main() {

    D d;
    MyTemplate<D> temp(d);
    temp.display();
   
    return 0;
}

使用模板时,并不知道模板类型到底是什么类型,可能针对不同类型的数据输出不同的结果,这个时候就需要使用 typeid 函数了。

[本章完...]

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容