RTTI (Runtime Type Information,运行时类型信息),它提供了运行时确定对象类型的方法,程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型。为什么会出现RTTI这一机制,这和C++语言本身有关系。和很多其他语言一样,C++是一种静态类型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用(Reference)本身的类型,可能与它实际代表(指向或引用)的类型并不一致。有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生了运行时类型识别的要求。和Java相比,C++要想获得运行时类型信息,只能通过RTTI机制,并且C++最终生成的代码是直接与机器相关的。
RTTI的功能由两个运算符实现:
- typeid运算符,用于返回表达式的类型。
- dynamic_cast运算符,用于将基类的指针或引用安全地转换成派生类的指针或引用。
当我们将这两个运算符用于某种类型的指针或引用,并且该类型含有虚函数时,运算符将使用指针或引用所绑定对象的动态类型
这两个运算符特别适用于以下情况:我们想使用基类对象的指针或引用执行某个派生类的操作并且该操作不是虚函数。但是一般来说,最好使用虚函数。(等下再解释啥使用用RTTI)
dynamic_cast运算符
其是C++四大转换运算符之一。使用形式如下:
dynamic_cast<type*>(e)
dynamic_cast<type&>(e)
dynamic_cast<type&&>(e)
// 其中,type必须是一个类类型,并且通常情况下该类型必须含有虚函数。在第一种形式中,e必须是一个有效的指针;第二种类型中,e必须是一个左值;在第三种形式中,e不能是左值。
在上面的所有形式中,e的类型必须符合以下三个条件中任意一个:e的类型是目标type的共有派生类,e的类型是目标type的公有基类或者e的类型就是目标type的类型。如果符合,则类型转成成功。否则,转换失败。如果转换指针形式失败,则返回0。如果转换目标是引用类型并且失败了,则运算符抛出一个bad_cast异常。
指针类型的dynamic_cast
class Base {
public :
void fun() {
cout << "Base's fun!" << endl; }
virtual ~Base(){
}
};
class Derived : public Base {
public:
void fun() {
cout << "Derived's fun!" << endl; }
};
int main() {
Base *bp = new Base();
if (Derived *dp = dynamic_cast<Derived*>(bp)) {
dp->fun();
}
else {
bp->fun();;
}
}
// 这里转换不会成功(返回0),因为bp是指向Base的指针,为什么会不成功呢?
// 多态是基类指针/引用指向基类,然后基类指针去调用虚函数,在运行的时候,编译器会依据基类指针实际指向的派 // 生类调用接口;但是这个时候,如果想调用的不是虚函数,而是派生类的函数怎么办,就需要通过强制转换转成派 // 生类指针。
// 将上面的bp指针指向Derived:
Base *bp = new Derived();
// 这个时候就会调用Derived的fun。
可以对一个空指针执行dynamic_cast,结果是所需类型的空指针。