RTTI:运行阶段类型识别,这是新提那家的C++特性。很多老师的编译器不支持。
RTTI的目的:为程序在运行阶段确定度意向的类型提供的一种标准的方式。
RTTI的用途:可以把一个基类的所有的派生类的地址转换成基类的指针,也即是向上转换,但是如何知道基类的指针指向的是那个对象呢?RTTI提供了了解决的方法。
RTTI的工作原理:
C++有3种支持RTTI的元素:
1、dynamic_cast:将使用一个指向Base class的pointer来生成一个指向Derived class的pointer。(向上转换)
2、typeid:返回一个指出对象类型的值
3、typeinfo:这是一个类,定义了有关特定类型的信息
只能将RTTI用于包含虚函数的类层次结构,原因在于只有对于这种类层次结构,才应该讲派生对象地址赋给基类指针。
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<typeinfo>
using namespace std;
class Base{
private:
int hold;
public:
Base(int h=0):hold(h){}
virtual void Speak() const {cout<<"I am Base class!"<<endl;}
virtual int Value() const {return hold;}
};
class A:public Base
{
public:
A(int h=0):Base(h){}
void Speak()const {cout<<"I am A class!"<<endl;}
virtual void Say() const {cout<<"I hold the value:"<<Value()<<endl;}
};
class B:public A
{
public:
B(int h=0,char cv='B'):A(h),ch(cv){}
void Speak() const {cout<<"I am B class!"<<endl;}
void Say() const {cout<<"I hold the value:"<<Value()<<" and a character:"<<ch<<endl;}
private:
char ch;
};
Base* getClass();
int main()
{
srand(time(0));
Base *p=NULL;
A *q=NULL;
for(int i=0;i<5;i++)
{
p=getClass();
p->Speak();
if(q=dynamic_cast<A*>(p)){ //如果类型转换成功,q的值为非0,如果转换失败,q为0.
q->Say();
}
if(typeid(B)==typeid(*p)){
cout<<"typeid:B class!"<<endl;
}
}
return 0;
}
Base* getClass()
{
Base *p=NULL;
switch(rand()%3)
{
case 0: p=new Base(rand()%100);
break;
case 1: p=new A(rand()%100);
break;
case 2: p=new B(rand()%100,'A'+rand()%25);
break;
}
return p;
}
必须是有虚函数的Base类,并且在派生类中重新定义。
也可以将dynamic_cast用于引用。当时没有雨空指针对应的引用。姿势回抛出一个bad_cast异常。
#include<typeinfo>
......
try{
A &rs = dynamic_cast<A&>(p);
}
catch(cad_cast &e)
{
<span style="white-space:pre"> </span>......
};