说明:部分内容来自<<程序员面试宝典>>和RTTI百度百科。
RTTI(run type identification):通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。有些读者认为设计类时使用虚函数就已经足够了,可是虚函数本身有局限性,当涉及类别阶层时,需要判断某个对象所属的类别,而因为类别设计中大量使用虚函数,所以使得这一工作难以实现,但又极其重要,于是使用RTTI的typeid运算符能使程序员确定对象的动态类型。
typeid操作符:返回指针和引用所指的实际类型
dynamic_cast操作符:将基类类型的指针或引用安全转换为派生类型的指针或引用。(一个实际指向子类对象的指针被转换成了父类指针,然后再用dynamic_cast转换回来,一定会成,而一个实际指向父类对象的指针,被dynamic_cast转换为子类指针,一定会失败。成功返回1,失败返回0)
#include<iostream>
using namespace std;
class base
{
public:
virtual void funcA()
{
cout<<"base"<<endl;
}
};
class derived:public base
{
public:
virtual void funcB()
{
cout<<"derived"<<endl;
}
};
void funC(base *p)
{
derived *dp=dynamic_cast<derived *>(p);//p是要转换的指针,将指针p的类型转换为(derived *)类型
if(dp!=NULL)
dp->funcB();
else
p->funcA();
}
void funcD(base *p)
{
derived *dp=NULL;
if(typeid(*p)==typeid(derived))//如果p是指针,typeid(*p)返回p所指派生类类型,typeid(p)返回基类类型
{
dp=static_cast<derived *>(p);
dp->funcB();
}
else
p->funcA();
}
int main()
{
base *cp=new derived;
cout<<typeid(cp).name()<<endl;//打印cp类型名
cout<<typeid(cp).name()<<endl;
funcD(cp);
funcC(cp);
base *p=new base;
funcC(dp);
funcD(dp);
return 0;
}
打印:
class base *
class base *
derived
derived
base
base
dynamic_cast和static_cast区别:
static_cast是c的强制转换,有一定的冒险性(信息丢失,内存越界)。
dynamic_cast是尝试性的转换,具有类型检查功能。转换成功返回新类型的合法指针,转换失败返回空指针。比较安全。
当我们能确定转换是安全的时候用static_cast更快一些。