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 函数了。

[本章完...]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容