typeid 操作符 用于判断数据的类型,使用时要包括<typeinfo>头文件。它是一个操作符而不是函数,类似的 sizeof 也是操作符不是函数。
成员函数.name()返回的是C-style字串类型,是数据类型的“名称”,或者理解为是一个“缩写”形式。具体值由编译器的实现所决定,可能编译器不同返回值也不同(标准只要求实现为每个类型返回唯一的字符串)。
用法:
typeid(变量、常量、或数据类型).name()
以下写法都被允许:
int num=123; cout << typeid(num).name(); cout << typeid(int).name(); cout << typeid(123).name();
例外:auto 类型不能直接使用: typeid( auto )
下面的代码,是我把大部分数据都罗列一遍,以测试它们各自的类型返回值:
注:源代码使用了 auto 变量,编译时请带上编译命令参数 -std C++1y
#include <iostream> #include <typeinfo> #include <string> #include <array> #include <vector> #include <list> #include <set> #include <map> #define idType(s) cout<<typeid(s).name()<<endl using namespace std; string myStr(string s){ return s; } class cc { public: virtual void vvf() {} }; class cpp : public cc {}; int main(void) { string a = "abcd"; string b = "1234567890"; // "" // string("") const char *c = "abc123"; char d[30] = "abc"; char e = 'a'; short f = 123; int g = 123456789; long h = 123456789; long long i = 1234567890; float j = 123.456; double k = 1.23e-45; long double l = 1.2e+308; bool m = true; void *n; char *o; int *p; long *q; string *r; struct ss {long l;}; struct tt {int i=0;int j=1;}; union uu {char name;int id;}; enum vv { Mon=0, Tue = 1, Thi }; class ww {}; auto x = "abc"; auto y = 1; auto z = -1.23; unsigned int ui; unsigned char uc; unsigned short us; unsigned long ul; unsigned long long ull; size_t pos; array<int,6> arr; vector<string> vct; list<int> lst; set<int> set; map<int,string> map; //容器种类大概有16种左右,其它略 cout << typeid(a).name() << endl; cout << typeid(b).name() << endl; cout << typeid("").name() <<endl; cout << typeid(string("")).name() <<endl; idType(c); idType(d); idType(e); idType(f); idType(g); idType(h); idType(i); idType(j); idType(k); idType(l); idType(m); idType(n); idType(o); idType(p); idType(q); idType(r); idType(ss); idType(tt); idType(uu); idType(vv); idType(ww); idType(x); idType(y); idType(z); cout<<endl; idType(ui); idType(uc); idType(us); idType(ul); idType(ull); cout<<endl; idType(pos); idType(arr); idType(lst); idType(vct); idType(set); idType(map); cout<<endl; idType(&a); idType(&f); idType(&m); idType(&x); idType(&y); idType(&z); cout<<endl; cpp* p1 = new cpp; cc* p2 = p1; idType(p1); idType(p2); idType(*p1); idType(*p2); idType(&p1); idType(&p2); cout<<endl; idType(typeid(a).name()); //typeid().name()返回值的类型 idType(main()); //main()函数返回值的类型 idType(myStr("")); //xxxx()函数返回值的类型 idType(main); //main()函数的类型 idType(myStr); //xxxx()函数的类型 return 0; }
测试结果:
Ss
Ss
A1_c
Ss
PKc
A30_c
c
s
i
l
x
f
d
e
b
Pv
Pc
Pi
Pl
PSs
Z4mainE2ss
Z4mainE2tt
Z4mainE2uu
Z4mainE2vv
Z4mainE2ww
PKc
i
d
j
h
t
m
y
y
St5arrayIiLy6EE
St4listIiSaIiEE
St6vectorISsSaISsEE
St3setIiSt4lessIiESaIiEE
St3mapIiSsSt4lessIiESaISt4pairIKiSsEEE
PSs
Ps
Pb
PPKc
Pi
Pd
P3cpp
P2cc
3cpp
3cpp
PP3cpp
PP2cc
PKc
i
Ss
FivE
FSsSsE
--------------------------------
Process exited after 1.043 seconds with return value 0
请按任意键继续. . .
从结果可以总结得到下图:(辛苦手工制作容我打个水印 ^_^)
返回结果大部分能看明白,部分值还描述了长度大小;但是容器类型的描述规则除了名称外后面的内容靠猜很难想出答案来的,暂且搁置不管它了。
typeid 应用
真如网上所说typeid返回的值由各自的编译器决定的,那记住这些数据名称“缩写”也没啥用。还好,typeid在class type_info中重载了操作符 == 和 != 来用于判断,注意不能用 if (typeid(x).name == "Ss") 但可用 if (typeid(x).name == typeid(int).name)、 if (typeid(x).name == typeid(1.0f).name) 等等来判断 x 的数据类型:
void exam(auto x) { if (typeid(x).name()==typeid("").name()) { // do something ... } }
附录
<typeinfo> 源码结构 Classes type_info //contains some type’s information, generated by the implementation. This is the class returned by the typeid operator. (class) bad_typeid //exception that is thrown if an argument in a typeid expression is null (class) bad_cast //exception that is thrown by an invalid dynamic_cast expression, i.e. a cast of reference type fails (class) Synopsis namespace std { class type_info; class bad_cast; class bad_typeid; } Class std::type_info class type_info { public: virtual ~type_info(); bool operator==(const type_info& rhs) const noexcept; bool operator!=(const type_info& rhs) const noexcept; bool before(const type_info& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; type_info(const type_info& rhs) = delete; // cannot be copied type_info& operator=(const type_info& rhs) = delete; // cannot be copied }; Class std::bad_cast class bad_cast : public exception { public: bad_cast() noexcept; bad_cast(const bad_cast&) noexcept; bad_cast& operator=(const bad_cast&) noexcept; const char* what() const noexcept override; }; Class std::bad_typeid class bad_typeid : public exception { public: bad_typeid() noexcept; bad_typeid(const bad_typeid&) noexcept; bad_typeid& operator=(const bad_typeid&) noexcept; const char* what() const noexcept override; };