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 函数了。
[本章完...]
网友评论