C++学习笔记28:运行期型式信息

时间:2023-03-09 19:12:47
C++学习笔记28:运行期型式信息

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();
}
}