RTTI(Run-Time Type Identification)
通过运行时类型识别,程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型。
RTTI这一机制,这和C++语言本身有关系。和很多其他语言一样,C++是一种静态类型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用(Reference)本身的类型,可能与它实际代表(指向或引用)的类型并不一致。有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生了运行时类型识别的要求。
RTTI提供了两个非常有用的操作符:typeid
和dynamic_cast
。
typeid操作符,返回指针和引用所指的实际类型;
dynamic_cast操作符,将基类类型的指针或引用安全地转换为其派生类类型的指针或引用。
dynamic_cast是c++中的动态转换类型,通常用作向下转换【基类到派生类】和平行转换【基类到基类】,其表达式使用格式如下: dynamic_cast<type *>(source *)
; ,运行时,程序会检查source是不是与type类型相兼容,如果是,表达式就返回一个派生类地址,然后转换为type*类型,否则则返回一个NULL
。
示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
class X { public: virtual void fun(){}; };
class XX : public X { void test(){};};
class Y { void haha(){};};
class Shape
{
public: virtual void fun(){};
};
class Rect :public Shape
{
public:
void fun(){};
void prin(){ cout << "i am Rectangle" << endl; }
};
class Circle :public Shape
{
public:
void fun(){};
void prin(){ cout << "i am circle" << endl; }
};
void fun(Shape *p)
{
if (typeid(*p) == typeid(Rect))
{
Rect *r = dynamic_cast<Rect *>(p);
r->prin();
}
if (typeid(*p) == typeid(Circle))
{
Circle *c = dynamic_cast<Circle *>(p);
c->prin();
}
}
int main()
{
Rect r;
cout << "first call fun";
fun(&r);
Circle c;
cout << "second call fun";
fun(&c);
int n = 0;
XX xx;
Y y;
Y *py = &y;
// int和XX都是类型名
cout << typeid(int).name() << endl;
cout << typeid(XX).name() << endl;
// n为基本变量
cout << typeid(n).name() << endl;
// xx所属的类虽然存在virtual,但是xx为一个具体的对象
cout << typeid(xx).name() << endl;
// py为一个指针,属于基本类型
cout << typeid(py).name() << endl;
// py指向的Y的对象,但是类Y不存在virtual函数
cout << typeid(*py).name() << endl;
return 0;
}