问题标签 [diamond-problem]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
7 回答
15246 浏览

c++ - 钻石继承 (C++)

我知道拥有钻石继承权被认为是不好的做法。但是,我有两个案例,我觉得钻石继承非常适合。我想问一下,你会建议我在这些情况下使用钻石继承,还是有其他设计可以更好。

案例 1:我想在我的系统中创建代表不同类型“动作”的类。这些动作按几个参数分类:

  • 动作可以是“读”或“写”。
  • 动作可以有延迟或无延迟(它不仅仅是 1 个参数。它显着改变了行为)。
  • 动作的“流类型”可以是 FlowA 或 FlowB。

我打算有以下设计:

当然,我会遵守没有 2 个动作(从 Action 类继承)将实现相同的方法。

案例 2:我在我的系统中为“命令”实现复合设计模式。一个命令可以读、写、删除等。我也想有一个命令序列,也可以读、写、删除等。一个命令序列可以包含其他命令序列。

所以我有以下设计:

此外,我还有一种特殊的命令,“现代”命令。一个命令和复合命令都可以是现代的。成为“现代”会为一个命令和复合命令添加特定的属性列表(它们的属性大多相同)。我希望能够持有指向 CommandAbstraction 的指针,并根据所需的命令类型(通过 new)对其进行初始化。所以我想做下面的设计(除了上面的):

同样,我将确保没有 2 个从 CommandAbstraction 类继承的类将实现相同的方法。

谢谢你。

0 投票
6 回答
30367 浏览

c++ - 多重继承+虚函数混乱

我有一个像这样的菱形多重继承场景:

公共父节点 A 定义了一个虚函数 fn()。
B和C都可以定义fn()吗?
如果是,那么下一个问题是 - D 可以无歧义地访问 B 和 C 的 fn() 吗?我假设这有一些语法..
D 是否有可能在不知道具体谁是 B 和 C 的情况下这样做?B 和 C 可以被其他一些类替换,我希望 D 中的代码是通用的。

我想要做的是让 D 以某种方式枚举它在其祖先中拥有的所有 fn() 实例。这是否可能以其他方式表示虚拟功能?

0 投票
8 回答
5526 浏览

java - java中的多重继承

Java 不允许从多个类继承(它仍然允许从多个接口继承。),我知道它非常符合经典的菱形问题。但我的问题是,为什么在从多个基类继承时没有歧义(因此没有钻石问题的机会)时,java 不允许像 C++ 那样的多重继承?

0 投票
3 回答
1895 浏览

c++ - 钻石问题

我正在经历钻石问题,并认为可以在各种情况下工作。这是我正在研究的其中之一。

我现在想知道如何访问 MainBase 类 mainbase 变量?任何输入。

0 投票
3 回答
742 浏览

c++ - Acceptable to use virtual inheritance to prevent accidentally creating a diamond?

This is a simplification of some real code, and a real mistake I made when I didn't realize someone else had already implemented Foo and derived from it.

EDIT: to save you from having to run this code...

  • If run as-is, it prints "fail" (undesireable, hard to debug).
  • If you delete the line marked "oops" it prints "Foo" (desired behavior).
  • If you leave the "oops" and make the two inheritances virtual, it won't compile (but at least you know what to fix).
  • If you delete the "oops" and make them virtual, it will compile and will print "Foo" (desired behavior).

With virtual inheritance, the outcomes are either good or compiler-error. Without virtual inheritance, the outcomes are either good or unexplained, hard-to-debug runtime failure.


When I implemented Bar, which basically duplicated what Foo was already doing, it caused the dynamic cast to fail, which meant bad things in the real code.

At first I was surprised there was no compiler error. Then I realized there was no virtual inheritance, which would have triggered the 'no unique final overrider' error in GCC. I purposefully chose not to use virtual inheritance since there aren't supposed to be any diamonds in this design.

But had I used virtual inheritance when deriving from Base, the code would have worked just as well (without my oops), and I would have been warned about the diamond at compile time vs. having to track down the bug at run time.

So the question is -- do you think it's acceptable to use virtual inheritance to prevent making a similar mistake in the future? There's no good technical reason (that I can see) for using virtual inheritance here, since there should never be a diamond in the design. It would only be there to enforce that design constraint.

0 投票
4 回答
772 浏览

c++ - 钻石继承问题

只是为了好玩,我正在为 Windows 开发一个 XUL 实现。在 XUL 中,UI 元素可以像这样用 XML 编写:

我正在考虑一个获取和设置元素属性的系统。它工作得很好,但我不确定在这里使用钻石继承是否有潜在危险。我在下面发布了一个完整的代码示例:

我认为没关系,因为基类 Attributes 没有数据成员,所以那里不会出现冲突。但我想我会与社区核实。非常感谢您的见解!

编辑 关于“is-a”与“has-a”,以及“偏好组合优于继承”的评论我有这样的说法:

  • 这里继承有一个优势。如果 Element 继承了 Width ,则强制实现 getWidth 和 setWidth 方法。所以添加一个属性意味着元素界面的“自动”更新。
  • 我最初将这些类命名为 AttributeController、WidthController 和 HeightController,但我发现它们太冗长了。你可以说我的 Element 是一个属性控制器。(好吧,这很蹩脚,但并非不真实!)
  • 进一步证明:Width 和 Height 的定义不包含任何数据成员。Element 类实际上它们。Width 和 Height 类只提供接口。所以这更像是一种可以做的关系。
0 投票
4 回答
17141 浏览

oop - 钻石问题

关于钻石问题的维基百科:

“...菱形问题是当两个类 B 和 C 继承自 A,而类 D 继承自 B 和 C 时出现的歧义。如果 D 中的方法调用 A 中定义的方法(并且不覆盖该方法),并且 B 和 C 以不同的方式覆盖了该方法,那么它从哪个类继承:B 还是 C?”

所以钻石看起来像这样:

我的问题是,如果没有这样的 A 类会发生什么,但 B 和 C 又声明了相同的方法,比如 foo()。这不是同样的问题吗?为什么又叫钻石问题?

例子:

0 投票
7 回答
3911 浏览

java - Java:你怎么称呼这种多重继承歧义?

这是一个在 Java 中使用多接口继承的示例,但存在一个问题。

请注意,我完全知道为什么会出现问题,这不是我的问题的重点。问题是如何命名这种特定的多接口继承歧义,如果有名称的话。

例如,在 C++ 中,当您使用多重实现继承并且无法确定要使用哪个覆盖方法时出现的歧义称为“钻石问题”:

http://en.wikipedia.org/wiki/Diamond_problem

现在再一次,我知道这不是同一个问题:这不是重点。关键是在之前的案例中已经创造了一个名称。

我想知道我将要描述的问题是否存在名称。

这是另一种多重继承的示例,其中一个接口继承自其他两个具有不兼容方法返回类型的接口:

(注意使用 'extends' 关键字在工作中的多接口继承)

你不能这样做,因为:

A 型和 B 型不兼容;都定义了 c() 但返回类型不相关

有没有创造一个名字来描述这种情况?

0 投票
2 回答
2548 浏览

c++ - C ++多重继承防止钻石

有没有办法在 C++ 中定义一个类 Foo 以便

  1. 我可以继承它
  2. 我不能从中“继承钻石”

IE

0 投票
6 回答
669 浏览

c++ - 为什么这个菱形图案有歧义?

我不确定这是否称为钻石问题,但为什么这不起作用?

我已经给出了 for 的eat()定义D。所以,它不需要使用B's 或C' 副本(所以,应该没有问题)。

当我说a->eat()(记住eat()不是虚拟的)时,只有一种可以eat()调用,即A.

那么,为什么我会收到此错误:

'A' 是 'D' 的模棱两可的基础


A *a = new D();对编译器到底意味着什么?

为什么我使用时不会出现同样的问题D *d = new D();