RTTI
- 运行期标识对象的型式信息
- 优势:允许使用指向基类的指针或引用自如地操作派生类的对象
- typeid:获取表达式的型式;type_info:型式信息类
- 头文件:typeinfo
对象转型模板
- dynamic_cast:动态转型
- static_cast:静态转型
- reinterpret_cast:复诠转型
- const_cast:常量转型
typeid操作符与type_info类
type_info类
- 编译器实现的动态型式信息型式
- 用于在程序运行时保存数据对象的型式信息
- 不能直接使用该类,只能通过typeid操作符
- 调用成员函数name()可以获得类的名称
typeid操作符
//programmer类是Employee的派生类 #include <typeinfo> Programmer P; Employee &e = P; //输出P实际类名的字符串“programmer” cout << typeid(e).name() << endl;
dynamic_cast
动态转型的三种方式:
向上转型:沿着类继承层次向基类转型
向下转型:沿着类继承层次向派生类转型
交叉转型:沿着类多重继承层次横向转型
指针的动态转型
正确执行时,结果为指向目标类对象的指针
错误执行时,结果为0/NULL(C++11:nullptr)
引用的动态转型
正确执行时,结果为目标类对象的引用
错误执行时,引发bad_cast异常
例子:假设软件公司包括程序员和经理两类职员,需要按照不同规则支付薪水和奖金,如何实现呢?
class Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Manager :public Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Programmer :public Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Company { public: virtual void PayRoll(Employee *e); virtual void PayRoll(Employee &e); private: vector<Employee *> _employees;//向量保存雇员 }; void Company::PayRoll(Employee *e)//版本1 { //调用哪个成员函数,如何区分程序员和经理 e->PaySalary(); e->PayBonus(); } void Company::PayRoll(Employee *e)//版本2 { Programmer *p = dynamic_cast<Programmer *>(e); if (p) //p确实指向程序员对象 { p->PaySalary(); p->PayBonus(); } else//p不指向程序员,不发奖金 { e->PaySalary(); } } void Company::PayRoll(Employee &e)//版本3 { try { Programmer &p = dynamic_cast<Programmer&>(e); p.PaySalary(); p.PayBonus(); } catch (std::bad_cast) { e.PaySalary(); } }
怕什么真理无穷,进一寸有一寸的欢喜。---胡适