【问题标题】:Are Virtual Base classes a workable and or useful feature虚拟基类是一个可行和/或有用的功能吗
【发布时间】:2015-01-15 13:10:47
【问题描述】:

我了解虚拟基类机制的存在是为了防止“钻石”问题。但是我很好奇是否通过重新设计类层次结构不能更好地处理这种情况。 以下面的案例为例:copied from here

class A { public: void Foo() {} };
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};

我看到现在存在的机制存在的问题是,您需要能够预测某人将会出现并从 B 和 C 继承。所以并不意味着我们最好用标记每个继承虚拟的?

【问题讨论】:

  • 是的,我们可以做到这一点请参阅我在 SO stackoverflow.com/questions/27457101/… 上提出的问题。但它会很混乱,很难阅读该代码。
  • 从 C 和 D 继承应该可以正常工作。 A(但不是 C)。 A 类实际上是在两条链中继承的。将只有一个 A 子对象。但是,是的,这是对必须在最高继承级别做出决定的机制的有效批评。埃菲尔语言的创造者伯特兰·迈耶(Bertrand Meyer)详细阐述了这一点。
  • 虚拟继承普通继承的成本不同。
  • 另外,您可能想了解所谓的“mixins”,但 IIRC 目前几乎没有库正在使用这种方法
  • 也许应该从头开始设计或避免复杂的类层次结构?这意味着如果你想要一颗钻石,你应该设计一颗钻石,而不仅仅是用你发现的钻头来创造。

标签: c++ class virtual


【解决方案1】:

A的虚拟继承意味着

  • A 必须在最派生类中初始化,并且
  • 访问A 事物的效率会有所降低(因为A 子对象可以在多个派生类对象之间共享,因此可以在每个对象中处于动态偏移)。

出于这些原因,使用虚拟继承时要小心。

一个好的经验法则是对接口使用虚拟继承,而不是对实现类。

【讨论】:

    【解决方案2】:

    您可以在virtual 成员函数上争论相同的观点——为什么不将所有成员函数都设为virtual,因为如果有人出现并从您的class 继承,他们可能希望能够覆盖您的成员函数。我们不这样做是因为对于virtual 基类,virtual 成员函数具有与之相关的额外成本(时间/资源开销和复杂性)。

    【讨论】:

    • 不完全是。作为类设计者,您可以通过执行纯虚拟(抽象)或虚拟析构函数(是的,继续继承)之类的事情来指定继承的意图。您未声明为虚拟的函数只是被继承,而您打算覆盖的函数被声明为虚拟。在虚拟基类中,一旦你声明了一个类,其他人就可以来创建“钻石”
    【解决方案3】:

    虚拟继承是所有具有多重继承功能的语言中的必备功能。虽然有可能所有的继承案例都是虚拟的,但这有:

    • 额外费用
    • 并不总是预期的结果

    因为虚继承是继承的一种特例,继承的是类的直接派生指令,而不是类本身。结果,虚拟地派生另一个类的每个基类都将这个虚拟基类作为直接基类提供给每个下一个派生类。当然,如果多个基类提供了同一个虚拟基类,会导致被派生类派生一次,但这是因为这多个基类提供了多个派生指令,但是一个类(与普通继承相比,在哪种情况基类将提供基类的多个子对象)。

    它始终是直接基类这一事实的结果是,它需要在每个下一个派生类中显式构造。当然,默认构造函数规则适用,但 C++ 在这条规则中甚至没有结果——基类初始化虚基的代码被接受;唯一被拒绝的情况是虚拟基础在多个基类中“竞争性初始化”——在这种情况下,您必须通过提供构造规范来“解决冲突”。

    请不要因为蹩脚的自我推销而抨击我,但我在这里更详细地描述了这个话题:

    https://sektorvanskijlen.wordpress.com/2010/12/08/multiple-inheritance-considered-nice

    【讨论】:

      猜你喜欢
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 2014-09-20
      相关资源
      最近更新 更多