C++11 @5

作者: Drew_MyINTYRE | 来源:发表于2022-02-04 14:52 被阅读0次

    类的派生和继承

    Java 中虽然没有类的多重继承,但一个类可以实现多个接口,这其实也算是多重继承了。相比 Java 的这种设计,C++ 中类的多重继承太过灵活,使用时需要特别小心,否则菱形继承的问题很难避免。

    class  Derived : private Base, public VirtualBase {
      // 注意,如果没有指定派生方式的话,默认为 private 方式
    }
    

    虚函数、纯虚函数和虚析构函数

    Java 语言里,多态 是借助派生类重写(override)基类的函数来表达,而 抽象 则是借助抽象类(包括抽象方法)或者接口来实现。而在 C++ 中,虚函数纯虚函数 就是用于描述 多态抽象 的利器:

    • 虚函数:基类定义虚函数,派生类可以重写(override)它。

    当我们拥有一个派生类对象(通过基类引用类型或者基类指针类型的变量实例化)来调用该对象的虚函数时,被调用的虚函数是派生类重写过的虚函数(如果该虚函数被派生类重写了的话)。

    对于上面的情况,Java 是怎么样的?

    • 纯虚函数:拥有纯虚函数的类不能实例化。从这一点看,它和 Java 的抽象类和接口非常类似。
    //虚函数由 virtual 标示
    virtual void getResult(bool isHardCode) {
        cout << "Happy new year" << endl;
    }
    
    //纯虚函数由"virtual"和"=0"同时标示
    virtual void doAction(int x, int y) = 0;
    

    Tips:

    • 派生类重写虚函数时候最好添加 override 标识,这样编译器能做一些额外检查而能提前发现一些错误。

    • 虚函数被 override 的时候,基类和派生类声明的虚函数在 函数名参数等信息上需保持一致。

    • 对析构函数而言,由于析构函数的函数名必须是 ~类名,所以 派生类基类析构函数名 肯定是不同的。

    • 通过基类指针来删除派生类对象时,是派生类对象的析构函数被调用。所以,当基类中如果有 虚函数 的时候,一定要记得将其 析构函数 变成 虚析构函数 。(注意,析构函数也是函数,和普通函数没什么区别)

    virtual ~ Father() {
       cout << "Init Father::~ Father()" << endl;
    }
    
    Father *father = new Son("WWE", 25);
    ...
    
    //由于 Father 的析构函数是虚函数,所以 Son 的析构函数被调用
    delete father;
    
    // 这样就会直接调用基类的析构函数
    // 运行时,~ Son()将先被调用。
    father->~ Father()
    

    在 C++ 中,也可以阻止某个虚函数被 override,方法和 Java 类似,就是在函数声明后添加 final 关键词。

    // test1 将不能被派生类 override 了
    virtual void test(boolean test) final;
    

    小结:

    • 如果想实现多态,就在基类中为需要多态的函数增加 virtual 关键词;

    • 如果基类中有虚函数,也请同时为基类的析构函数添加 virtual 关键词。只有这样,指向派生类对象的基类指针变量被 delete 时,派生类的析构函数才能被调用。

    构造和析构函数的调用次序

    • 对构造函数而言,基类的构造函数 先于 派生类构造函数被调用;

    • 如果派生类有多个基类,则按照在派生列表里的顺序调用各自的构造函数。

    // 比如 Derived 派生列表中基类的顺序是:先 Base,然后是 VirtualBase。
    // 所以 Base 的构造函数先于 VirtualBase 调用,最后才是 Derived 的构造函数。
    class  Derived : private Base, public VirtualBase {
    }
    
    • 析构函数则是相反的过程,即派生类析构函数先被调用,然后再调用基类的析构函数。

    • 如果是多重继承的话,则按照它们在派生列表里出现的相反次序调用各自的析构函数。

    // Derived 类实例析构时,Derived 析构函数先调用,然后 VirtualBase 析构,最后才是 Base 的析构。
    class  Derived : private Base, public VirtualBase {
    }
    

    相关文章

      网友评论

          本文标题:C++11 @5

          本文链接:https://www.haomeiwen.com/subject/kdjkkrtx.html