4-1运行时类型识别RTTI
[TOC]
1.RTTI
Run-Time Type Identification
运行时类型识别
- 使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。
2.操作符typeid
等同于sizeof这类的操作符。
返回结果是名为type_info的标准库类型的对象的引用。
头文件typeinfo
- 它的表达式有下图两种形式:
NAME | TYPEID | TYPE |
---|---|---|
typeid | 类型ID | typeid(type) |
typeid | 运行时刻类型ID | typeid(expr) |
// type_info类的源码
class type_info {
public:
const char *name() const;
bool operator==(const type_info& rhs) const;
bool operator!=(const type_info& rhs) const;
int before(const type_info& rhs) const;
virtual ~type_info();
private:
......
};
typeid使用注意事项
Ⅰ typeid返回一个type_info对象的引用;
Ⅱ 如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数;
Ⅲ 只能获取对象的实际类型。
3.操作符dynamic_cast
- 允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型。
dynamic_cast使用注意事项
Ⅰ 只能应用于指针和引用的转换;
Ⅱ 要转换的类型中必须包换虚函数;
Ⅲ 转换成功返回派生类的地址,失败返回NULL。
4.代码示例
// 鸟类和飞机类都会“降落”和“起飞”,因此“降落”和“起飞”的特性写入一个接口类中
// 鸟类会“觅食”,并继承接口类的“降落”和“起飞”
// 飞机类会“负重”,并继承接口类的“降落”和“起飞”
// 传入一个基类指针,调用对象的“降落”和“起飞”。并根据对象的类型的不同,分别调用各自的“觅食”或“负重”
void doSomething(Flyable *obj) {
obj->takeoff();
cout << typeid(*obj).name() << endl;
if(typeid(*obj) == typeid(Bird)) {
Bird *bird = dynamic_cast<Bird *>(obj);
bird->foraging(); // 如果是Bird,则觅食
}
if(typeid(*obj) == typeid(Plane)) {
Plane *plane = dynamic_cast<Plane *>(obj);
plane->carry(); // 如果是Plane,则负重
}
obj->land();
}