Skip to content

Latest commit

 

History

History
54 lines (41 loc) · 2.23 KB

08_类层次结构.md

File metadata and controls

54 lines (41 loc) · 2.23 KB

运行时类型信息

在运行时对类型信息的使用一般称为"运行时类型信息",经常写成 RTTI

向下强制、向上强制与交叉强制

从基类到派生类的强制通常被称为向下强制。与此相对应,从派生类向基类的强制称为向上强制。从一个基类向其兄弟类的强制,称为交叉强制。

dynamic_cast 通过 RTTI 进行动态类型检查,能从多态性的虚基类强制到某个派生类或者兄弟类(实质也是派生类)。方法是通过一个到多态类型的指针或者引用,进行向下强制或交叉强制。

    pw ---> BBwindow                 Ival_box <--- pb
               ↑                         ↑
    ps ---> BBslider                Ival_slider
               ↑                         ↑
               +---- BB_ival_slider -----+
  • 向下强制: ps = dynamic_cast<BBslider*>(pw)
  • 向上强制: pw = static_cast<BBwindow*>(ps)
  • 交叉强制: pb = dynamic_cast<Ival_box*>(pw)

dynamic_cast 的专长是处理那些编译器无法确定转换正确性的情况。因为涉及到了运行时类型信息检查,所以使用 dynamic_cast 会有一点点的性能损耗。如果类型已知,我们就根本不需要用 dynamic_cast 。

dynamic_cast 的目标类型不必是多态的:

    class Io_obj {
        virtual Io_obj* clone() = 0;
    };
    class Io_date : public Date, public Io_obj {};
    void f(Io_obj* pio) {
        Date* pd = dynamic_cast<Date*>(pio);
    }

指向成员的指针

将取地址运算符应用到完全限定的类成员名,就能得到指向成员的指针。

    typedef void (Base::*pBase_mem)();  // 指向成员的指针的类型
    
    void f(Base* p) {
        pBase_mem s = &Base::base_func;
        p->base_func();         // 直接调用
        (p->*s)();              // 通过指向成员的指针调用
    }

一个派生类至少包含由它的基类继承来的成员。这也意味着我们可以安全地将一个指向基类成员的指针赋值给一个指向派生类的成员的指针,但反过来就不行:

    void (Base::*pBase_mem)() = &Derived::derived_func;     // 错误
    void (Derived::*pDerived_mem)() = &Base::base_func;     // OK