跳至主要內容

继承_多重继承

LincZero大约 2 分钟

继承_多重继承

多重继承(multipleinheritance,MI

  • 使用

    • 用逗号分隔,如class A: public APerent1, public APerent2 {...}
  • 多重继承带来的问题

    • 多重继承比单继承麻烦,也更容易出现问题

    • 多重继承会带来新的问题,其中两个主要问题:

      • 从两个不同的基类继承同名方法。解决方案:作用域解析运算符
      • 从两个或更多相关基类中继承同一个类的多个实例。解决方案:虚基类
    • 而虚基类该解决方案有会带来新的问题: - 构造时重复传参或无法传参 - 派生类无法调用虚基类的方法

    • 为了解决这些问题需要一些新规则和不同语法

【缺陷补丁】

【缺陷补丁】虚基类——解决多个类同祖先问题

使用

虚基类(virtual base class)与禁止传参给基类原则

  • 原理
    • 虚基类使得从多个类(他们的基类相同)派生出的对象只继承同一个基类对象(是基类对象而不是基类)
    • 即只有一个基类对象副本
    • 即新类如果多重继承这些类,也只会有一个基类对象
  • 特性
    • 禁止信息通过中间类传给基类
    • 因为如果继承多个由虚基类派生而来的类,构造基类时重复传参将出错
    • 这时需要新的写法——直接调用基类的基类的构造函数
    • 虚基类必须使用该新写法,而非虚基类,该写法是非法的
  • 写法
    • 例:class A : virtual public APerent {...}
    • 或:class A : public virtual Aperent {...}virtualpublic的次序无关紧要)
  • 多重继承的写法
    • 虚基类为避免重复传参的冲突,禁止信息通过中间类自动传递给基类,而需要显式地调用所需基类的构造函数
    • 如:A() : APerentPerent(), APerent1(), APerent2() {...}(补注:默认为私有继承)

带来新的问题

虚基类会带来新的问题

  • 重复传参问题(内置问题)
    • 解决方案(内置方案):进制信息通过中间量传给基类 ——> 无法传参的问题
  • 无法传参问题
    • 解决方案:显示调用所需的基类的构造函数

效率和成本

虚基类不是默认的方式,因为其有额外的开销(就像虚函数不是默认的方式那样)

  • 在一些情况下,可能需要基类的多个拷贝
  • 将基类作为虚基类需要额外的计算
  • 这样做有缺点

【缺陷解决】作用域解析运算符——解决基类同名函数问题

  • 解决方法
    • 方法一:使用作用域解析运算符,如a.APerent2::fn();
    • 方法二:重新定义方法,并指出要使用哪个基类版本的方法,如void a:fn(){APerent2::fn();}