简介:
RTTI,Runtime Type Information,即运行时类型信息,它提供了运行时确定对象类型的方法。
通过RTTI,能够通过基类的指针或引用来检索其所指对象的实际类型。c++通过下面两个操作符提供RTTI。
(1)typeid:返回指针或引用所指对象的实际类型。
(2)dynamic_cast:将基类类型的指针或引用安全的转换为派生类型的指针或引用。
对于带虚函数的类,在运行时执行RTTI操作符,返回动态类型信息;对于其他类型,在编译时执行RTTI,返回静态类型信息。
上以节中,已经介绍了dynamic_cast的用法,本节主要来看typeid的用法。
数据类型转换系列文章:
typeid的使用举例:
代码例子1:typeid用在普通类型
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
short s1 = 5;
unsigned ui1 = 20;
int i1 = 50, i2 = 100;
char ch1 = 'a';
wchar_t wch1 = L'b';
float f1 = 3.14159265f;
cout<<"typeid name:"<<endl;
cout<<typeid(s1).name()<<endl; // s
cout<<typeid(ui1).name()<<endl; // j
cout<<typeid(i1).name()<<endl; // i
cout<<typeid(ch1).name()<<endl; // c
cout<<typeid(wch1).name()<<endl; // w
cout<<typeid(f1).name()<<endl; // f
cout<<"typeid compare result:"<<endl;
if (typeid(i1) == typeid(i1)) {
cout<<"typeid(i1) == typeid(i2)"<<endl; //执行到这个语句(类型相等)
}else {
cout<<"typeid(i1) != typeid(i1)"<<endl;
}
if (typeid(s1) == typeid(i1)) {
cout<<"typeid(s1) == typeid(i1)"<<endl;
}else {
cout<<"typeid(s1) != typeid(i1)"<<endl; //执行到这个语句(类型不相等)
}
return 0;
}
/*
编译环境:mac os下用g++编译:
MacBook-Pro cpp_stu % g++ typeid_test1.cpp
*/
代码例子2:typeid用在类类型
1)
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
int a;
virtual void fun1() {cout<<"Base::fun1"<<endl;}
virtual void fun2() {cout<<"Base::fun2"<<endl;}
virtual void fun3() {cout<<"Base::fun3"<<endl;}
};
class A {
public:
int a;
};
class Derive : public Base{
public:
int b;
void fun2() {cout<<"Derive::fun2"<<endl;}
};
int main()
{
Base b;
Derive d;
A a;
cout<<typeid(b).name()<<endl; // 4Base
cout<<typeid(d).name()<<endl; // 6Derive
cout<<typeid(a).name()<<endl; // 1A
cout<<"compare result:"<<endl;
if (typeid(b) == typeid(d)) {
cout<<"typeid(b) == typeid(d)"<<endl;
}else {
cout<<"typeid(b) != typeid(d)"<<endl; //执行到这个语句
}
return 0;
}
/*
编译环境:mac os下用g++编译:
MacBook-Pro cpp_stu % g++ typeid_test2.cpp
*/
运行结果:
4Base
6Derive
1A
compare result:
typeid(b) != typeid(d)
分析:
2)
再看下面的代码:
Derive d;
Derive *pD = new Derive();
cout<<typeid(pD).name()<<endl; // P6Derive
if (typeid(d) == typeid(pD)) {
cout<<"typeid(d) == typeid(pD)"<<endl;
}else {
cout<<"typeid(pD) != typeid(pD)"<<endl; //执行到这个语句
}
显然,pD是指针类型,typeid(pD).name()的结果是P6Derive,而不是6Derive。
3)
再看一个例子,把上面的
Derive *pD = new Derive();
改为:
Base *pB = new Derive();, 如下:
Derive d;
Base *pB = new Derive();
cout<<typeid(pB).name()<<endl; // P4Base
cout<<typeid(*pB).name()<<endl; // 6Derive
cout<<"compare result:"<<endl;
if (typeid(d) == typeid(*pB)) {
cout<<"typeid(d) == typeid(*pB)"<<endl; //执行到这个语句
}else {
cout<<"typeid(pD) != typeid(*pB)"<<endl;
}
运行结果:
P4Base
6Derive
compare result:
typeid(d) == typeid(*pB)
分析:
d和 *pB的类型一样,都是Derive类型。
4)
上面的例子中,Base是虚基类(有虚函数),现在如果我们把Base改为非虚基类,看看typeid的结果如何。代码如下:
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
int a;
void fun1() {cout<<"Base::fun1"<<endl;}
void fun2() {cout<<"Base::fun2"<<endl;}
void fun3() {cout<<"Base::fun3"<<endl;}
};
class Derive : public Base{
public:
int b;
void fun2() {cout<<"Derive::fun2"<<endl;}
};
int main()
{
Derive d;
Base *pB = new Derive();
cout<<typeid(pB).name()<<endl; // P4Base
cout<<typeid(*pB).name()<<endl; // 4Base
cout<<"compare result:"<<endl;
if (typeid(d) == typeid(*pB)) {
cout<<"typeid(d) == typeid(*pB)"<<endl;
}else {
cout<<"typeid(pD) != typeid(*pB)"<<endl; //执行到这个语句
}
return 0;
}
/*
编译环境:mac os下用g++编译:
MacBook-Pro cpp_stu % g++ typeid_test3.cpp
*/
运行结果:
P4Base
4Base
compare result:
typeid(pD) != typeid(*pB)
分析:
Base *pB = new Derive();
创建的是Derive实例,但是typeid(*p B)的结果是4Base类型,而我们期望的是真正创建的对象的类型,即Derive。
这就是没有将父类定义成虚基类(包含virtual函数)的弊端。