2

C++:我有一个带有纯虚函数 f() 的基类 A,然后两个类 B 和 C 虚拟继承自 A,以及一个继承自 B 和 C 的类 D(典型的菱形结构):

   A f() = 0
 v/ \v
 B   C
  \ /
   D

在以下情况下,何时何地需要实现 f() = 0?

  1. B 和 C 也都有纯虚函数(-> 抽象类必须实现继承的纯虚函数吗?)
  2. 其中只有一个(B XOR C)具有纯虚函数(-> 另一个还必须实现 f() 吗?)
  3. B 和 C 都没有自己的纯虚拟(-> 跳过 B 和 C 中的实现并将其“传递”给 D 的可能方法?)
  4. 在上述三种情况下,D需要实现f()吗?在哪些情况下 D 可以选择实现 f()?在哪些情况下,如果有的话,D 不可能实现 f()?

对于这类问题,还有其他常见的建议吗?

谢谢。

4

4 回答 4

1

B 和 C 也都有纯虚函数(-> 抽象类必须实现继承的纯虚函数吗?)

是的, D 必须实现所有继承的纯虚函数。
除非一个类实现了类的所有纯虚函数,否则它派生自类本身就充当抽象类。

其中只有一个(B XOR C)具有纯虚函数(-> 另一个还必须实现 f() 吗?)

D必须实现它通过任何层次结构中的基类继承的纯虚函数。如果它的直接基类没有定义一个纯虚函数,那么这个类也变成了一个抽象类,除非D实现了继承的纯虚函数,它也会变成抽象类。

B 和 C 都没有自己的纯虚拟(-> 跳过 B 和 C 中的实现并将其“传递”给 D 的可能方法?)

D必须实现它通过A->B&继承的纯虚函数。请A-C注意,在这种情况下,两者B都是C抽象类。

在上述三种情况下,D需要实现f()吗?在哪些情况下 D 可以选择实现 f()?在哪些情况下,如果有的话,D 不可能实现 f()?

D需要foo()在上述所有 3 个条件下实现,才能实例化(非抽象)。

结论:

  1. 一个类需要实现它从它的所有基类继承的所有纯虚函数,否则将使该类成为抽象类。
  2. 虚拟属性是继承的,如果超类声明了一个虚拟函数,那么派生类中的重写函数也是虚拟的,它将虚拟属性传递给从它派生的所有类。

避免死亡钻石!除非你真的了解其中的微妙之处。很多人尝试使用虚拟继承,但实际上它并不是实现他们的设计想要实现的目标的最恰当方式。在某些情况下确实需要使用虚拟继承,但它仍然是语言提供的重要构造,但更多时候以错误的方式使用。因此,重新审视您的设计以验证您是否真的需要虚拟继承是有意义的。

以下可能是一个很好的阅读:

  1. 多重继承 - 第一部分
  2. 多重继承 - 第二部分
  3. 多重继承 - 第三部分
于 2011-09-16T15:42:16.247 回答
0

唯一的要求是,在“叶子”级别(最衍生的)所有东西都有一个实现(可能只有一个,否则如果 - 在您访问图表的点 - 在相同的“距离”有更多实现时,可能会出现歧义”。

所以 D 必须实现所有尚未实现的东西,或者所有东西都通过不同的路径多次实现(以消除歧义)。如果某些东西 - 在 D 级别 - 仍未实现...... D 不能被实例化,并且需要从 D 派生的 E 和 E 实现。

- 钻石恒久远 -

于 2011-09-16T15:50:05.350 回答
0
  1. 不,抽象类(大概是Band C)不需要实现继承的纯虚拟。不过,像这样的子类D需要这样做才能被实例化。

  2. B不,再次C将继承纯虚方法,只需要重写它即可生成最终的具体类。

  3. D是的,这将以两种方式之一通过实现传递给。如果BC两者都虚拟继承,那么D将实现一次。如果它们实际上不继承,则D需要同时覆盖the和 的B版本Cf使其具体化。

  4. 如果D是抽象的,它永远不需要实现f。假设你的意思是具体的,在所有三种情况下你都需要覆盖fin D。仅当两者BC覆盖都不需要时fD

仔细查看您的设计并删除钻石继承。在大多数情况下,这将是防止所有这些问题的最佳选择。

于 2011-09-16T15:55:01.570 回答
0

B 和 C 也都有纯虚函数(-> 抽象类必须实现继承的纯虚函数吗?

是的。从抽象类继承的任何类都必须实现虚函数才能实例化。否则它们也将是抽象的。

其中只有一个(B XOR C)具有纯虚函数(-> 另一个还必须实现 f() 吗?)

既然C也源于A,那也应该落实f()

B 和 C 都没有自己的纯虚拟(-> 跳过 B 和 C 中的实现并将其“传递”给 D 的可能方法?)

你可以这样做。但这会阻止实例化BC单独像 -

A *obj = new B(); // Error
A *obj = new C(); // Error

在上述三种情况下,D需要实现f()吗?在哪些情况下 D 可以选择实现 f()?在哪些情况下,如果有的话,D 不可能实现 f()?

f()D只要您确实希望它的所有父类都是抽象的,就可以单独实现。

于 2011-09-16T15:39:51.353 回答