运行时类型实别(RTTI)
RTTI 是 Run-time Type Identification 的缩写。RTTI为程序提供了一个标准方式用来在运行时决定对象的类型。也就是说RTTI允许指向基类的对象或引用在运行时恢复到其实际指的子类类弄。
通过以下两种方式提供RTTI操作:
l 通过typeid操作符,来返回通过指针或引用实际指的对象类型。
l 通过dynamic_cast操作符,安全的将基类指针或引用转为子类的指针或引用类型。
dynamic_cast 操作符
dynamic_cast 操作符在RTTI操作中经常用到,它是用来告诉我们是否能够全安的将一个对象的地址指针转换为一个具体的类型。
以下通过代码进行说明:
class Base { };
class Derived : public Base { };
int main()
{
Baseb;
Derivedd;
Base*pb = dynamic_cast<Base*>(&d); // #1
Derived*pd = dynamic_cast<Derived*>(&b); //#2
return0;
}
#1 可能通过编译,因为将子类转换成基类dynamic_cast永远成功
#2 编译失败因为如果不是多态方式下,dynamic_cast不允许将基类转换成子类。
向上转型或向转型
将子类的指针或引用转换成基类的指针或引用叫到向上转型,在公有继承中不需要特别处理类型转换。实个规则可以认为是is-a 的对象关系。一个子类对象继承了基类的所有数据及函数。基类能做的事情,子类也可以做。
向下转型与向上转型相反,是用来将一个基类对象的指针或引用转为子类对象的指针或引用。子类可能增加新的类成员,但这些新增加的类成员不能在基类中使用。
代码说明:
#include<iostream>
using namespacestd;
class Employee {
private:
int id;
public:
void show_id(){}
};
class Programmer :public Employee {
public:
void coding(){}
};
int main()
{
Employee employee;
Programmer programmer;
// upcast - implicit upcast allowed
Employee *pEmp = &programmer;
// downcast - explicit type cast required
Programmer *pProg = (Programmer*)&employee;
// Upcasting: safe - progrommer is anEmployee
// and has his id to do show_id().
pEmp->show_id();
pProg->show_id();
// Downcasting: unsafe - Employee doesnot have
// the method, coding().
// compile error: 'coding' : is not amember of 'Employee'
// pEmp->coding();
pProg->coding();
return 0;
}
typeid操作符
我们可以通过typeid操作符来检测两个对象类型是否相同。
代码如下:
#include<iostream>
#include<typeinfo>
using namespacestd;
class Employee {
private:
int id;
public:
void show_id(){}
};
class Programmer :public Employee {
public:
void coding(){}
};
int main()
{
Employee lee;
Programmer park;
Employee *pEmpA = &lee;
Employee *pEmpB = &park;
// check if two object is the same
if(typeid(Programmer) == typeid(lee)) {
Programmer *pProg = (Programmer*)&lee;
pProg->coding();
}
if(typeid(Programmer) == typeid(park)) {
Programmer *pProg = (Programmer*)&park;
pProg->coding();
}
pEmpA->show_id();
pEmpB->show_id();
return 0;
}