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();
    }
}
时间: 2024-08-10 21:27:47

C++学习笔记28:运行期型式信息的相关文章

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

static_cast 静态转型的用途 与dynamic_cast不同,static_cast不仅可以用于指针和引用,还可以用于其他型式 一般用于非类型式的普通数据对象转型 静态转型的问题 不进行运行期型式检查,不安全 若转型失败,结果无定义 const_cast 常量转型的目的 用于取消或者设置量的const状态(如设置为const或者取消const) 常量转型的问题 如果原始数据对象不能写入,则取消常量修饰可能会导致未知的结果 例子: #include <iostream> class C

51CTO学习笔记--Linux运维故障排查思路与系统调优技巧视频课程(高俊峰)

51CTO学习笔记--Linux运维故障排查思路与系统调优技巧视频课程 第一课 Linux运维经验分享与思路 1.一般把主机名,写到hosts下    127.0.0.1    hostname,因为很多应用要解析到本地.oracle没有这个解析可能启动不了. 2.注释掉UUID以及MAC地址,需要绑定网卡的时候,这个可能会有影响. 3.磁盘满了无法启动,  var下木有空间,无法创创建PID等文件,导致文件无法启动,按e   进入single  然后b  重启进入单用户模式. 4.ssh登陆系

【视频编解码&#183;学习笔记】11. 提取SPS信息程序

一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UINT8和UINT32都为小写表示,为了更符合编程规范,将其改为全大写(可使用ctrl+H在整个解决方案内进行替换). typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; 之后编

[原创]java WEB学习笔记28: 会话与状态管理Cookie 机制

1.会话与状态管理 1)背景 ① HTTP协议是一种无状态的协议,WEB服务器本身不能识别出哪些请求是同一个浏览器发出的 ,浏览器的每一次请求都是完全孤立的: ② 作为 web 服务器,必须能够采用一种机制来唯一地标识一个用户,同时记录该用户的状态: ③ 问题:怎么才能实现网上商店中的购物车呢:某个用户从网站的登录页面登入后,再进入购物页面购物时,负责处理购物请求的服务器程序必须知道处理上一次请求的程序所得到的用户信息. 2)会话和会话状态 ① WEB应用中的会话:指一个客户端浏览器与WEB服务

C++学习笔记30:模板与型式参数化

转型操作 接受目标型式作为模板参数 Programmer *p = dynamic_cast<Programmer*>(e) 模板工作原理 使用template<typename T>定义函数模板或者类模板 体化(instantiation):使用特定的模板实际参数,生成真正的模板函数和模板类 编译模板类和模板函数,生成最终的程序代码 模板代码 一般放在头文件中:编译器需要看到模板源文件 模板的特点: 抽象性:模板代码高度抽象,是函数和类的模范 安全性:型式检查能够发现大多数型式失

Linux学习笔记--free命令(查看内存信息的命令)

free,显示内存状态. 1. 命令格式: free [选项] 2. 常用选项: "free -b" 以 Byte 为单位显示内存使用情况. "free -k" 以 KB 为单位显示内存使用情况. "free -m" 以 MB 为单位显示内存使用情况. "free -g" 以 GB 为单位显示内存使用情况. "free -h" 人性化显示,自动选取合适的单位.(有的系统不支持此选项) "free

ArcGIS API for JavaScript 4.2学习笔记[28] 可视域分析【使用Geoprocessor类】

想知道可视域分析是什么,就得知道可视域是什么 我们站在某个地方,原地不动转一圈能看到的所有事物就叫可视域.当然平地就没什么所谓的可视域. 如果在山区呢?可视范围就会被山体挡住了.这个分析对军事上有十分重要的意义. 在本例中,可视域是以GraphicLayer中的Graphics[]形式存在的. 这个例子用到了Geoprocessor这个类.这个类的对象是如何判别我要进行可视域分析呢?且听我慢慢道来. 看看结果 点击山谷的位置,出现一个红点,稍等10s左右,出现橙色的面块,橙色的面块就是红点位置所

Nginx学习笔记09控制转发的信息

在使用proxy_pass配置项时,可以使用以下配置来控制转发给后端主机的HTTP头信息. (1)proxy_pass_header 向后端主机转发客户端请求中的HTTP头部. (2)proxy_hide_header 向后端主机隐藏客户端请求中的HTTP头部. (3)proxy_set_header 向后端主机发送额外的HTTP头部,可以新增HTTP头部,或者修改已有的HTTP头部. 不使用proxy_xxx_header进行HTTP头部信息控制的情况: Nginx配置: location ~

thinkphp5.0学习笔记(三)获取信息,变量,绑定参数

1.构造函数: 控制器类必须继承了\think\Controller类,才能使用: 方法_initialize 代码: <?php namespace app\lian\controller; use think\Controller; use think\Db; use think\Request; class Index extends Controller { public function _initialize() { echo 'init|||'; } public function