• 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();
        }
    }
    怕什么真理无穷,进一寸有一寸的欢喜。---胡适
  • 相关阅读:
    Uri编码,包括javascript前端与C#服务器端
    快速排序
    bootstrap
    boosting
    bagging
    SHELL排序
    冒泡排序
    插入排序
    选择排序
    二叉树的数学性质
  • 原文地址:https://www.cnblogs.com/hujianglang/p/6246867.html
Copyright © 2020-2023  润新知