问题标签 [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 投票
5 回答
19467 浏览

java - Java 8 中的抽象类和接口有什么区别?

在 Java 中,抽象类和接口之间曾经有一个微妙但重要的区别:默认实现。抽象类可以拥有它们,接口不能。Java 8 虽然引入了接口的默认实现,这意味着这不再是接口和抽象类之间的关键区别。

那是什么?

据我所知,唯一剩下的区别(可能除了一些底层效率的东西)是抽象类遵循传统的 Java 单继承,而接口可以有多重继承(如果你愿意,也可以有多重实现)。这让我想到另一个问题——

新的 Java 8 接口如何避免菱形问题

0 投票
1 回答
485 浏览

c++ - 通过 QObject 子类实现多重继承的最接近解决方案

我有多个 QObject 子类,它们应该充当接口类并由其他一些类(继承)实现。例如 letclass A : virtual public QObjectclass B : virtual public QObjectbe 接口类。我需要一个QDialog对象来实现它们的行为,例如:class X: public QDialog, A, B.

不幸的是,我在设计时没有仔细阅读文档,现在我意识到了两个事实:

  1. 将插槽实现为纯虚拟成员函数是不可能的,因为 moc 生成的代码需要调用它们。
  2. QObject 派生类不支持多重继承。那不是钻石的事。这是因为 moc 生成的代码不能static_cast将虚拟QObject对象A*通过虚拟基础。(这就是编译器所说的!)

什么是尽可能少地影响代码的最佳替代设计?我可以想到宏黑客。也许基类中的宏(如Q_OBJECT)将基类的所有成员、信号、插槽复制到派生类?

注意QObjects 不能被多次继承真的很糟糕。不是吗?

0 投票
3 回答
401 浏览

c++ - C ++如何初始化抽象基类引用元素?

我的问题是基于典型的钻石层次结构,但不是典型的钻石问题。

有一个抽象接口定义了许多功能(上面的例子被简化了)。然后有一些实现类一次只实现其中的几个功能。最后,还有一个非抽象类,如上面的 Device 类,通过将几个实现类组合在一起来实现整个接口。

现在,问题是这样的:

Interface 类中有一个整数元素,它由类 Device 初始化并在实现类之间共享,到目前为止一切都很好。但是如果我= 0Interface(int _value = 0)构造函数中删除,整个系统就会崩溃,因为我缺少接口类的默认构造函数,这有点奇怪,因为它永远不会被调用。

为什么这会困扰我?正如代码中所建议的,Interface 类需要包含对复杂数据结构(不属于该类)的引用,而不是在所有派生实现类之间共享。然而,为引用指定默认值既不明智也不可能。

所以问题是:

如何正确初始化接口类(引用)元素,例如SomeBigData &data代码中建议的,我无法为默认构造函数指定默认值(无论如何都不会调用)?还是我做错了什么?

0 投票
2 回答
2030 浏览

c++ - C++钻石继承构造函数?

我想知道我应该如何为我的第四堂课调用我的构造函数。A类是基类,B类和C类继承它。

现在我的第四类继承了 B 类和 C 类我应该如何为我的 D 类调用构造函数?

我尝试过这种方式,但我得到“没有匹配函数调用 ClassB::ClassB()â”

0 投票
2 回答
477 浏览

c++ - 没有数据成员的菱形(多重继承)

假设我们有通常的菱形图案:

请注意,基类A没有任何数据成员。它实际上只是一个纯虚方法的接口。

现在如果我这样做:

编译器会告诉我演员阵容不明确,因为有两个 A 基类。

但如果我这样做:

现在我有一个指向我的A基类之一的指针,我可以做到a->foo()

这安全吗?

我想知道的是我是否可以进行这种双重向上转换以仅具有指向接口(没有数据成员)的指针而没有虚拟继承的开销。无论如何,我不打算对指针进行向下转换或对其进行任何不调用虚拟方法的操作。

我知道这意味着有两个基类,但由于没有成员,这不重要,或者是吗?

EDIT:我正在努力寻找一种方法来实现接口,我想我只需要使用虚拟继承。

假设我有一个类Buffer(接口类)和一个BufferImplementation派生自它的类。

现在假设我有另一个接口IOBuffer(从另一个接口派生Buffer),其IOBufferImplementation类必须同时从BufferImplementation接口派生IOBuffer

在我之前的示例中,Buffer 为 A,BufferImplementation 为 B,IOBuffer 为 C,IOBufferImplementation 为 D。

0 投票
2 回答
985 浏览

c++ - Diamond inheritance

Assume classes D and E and F all inherit from base class B, and that class C inherits from D and E.

(i) How many copies of class B appear in class C?

(ii) How would using virtual inheritance change this scenario? Explain your answer.

(iii) How does Java avoid the need for multiple inheritance for many of the situations where multiple inheritance might be used in C++?

Here are some of my current ideas, but I'm an by no means an expert on C++!

(i) If C inherits from D and E which are subclasses of B, then would D and E technically be copies of their super class? Then if C inherits from D and E that would mean there are 2 copies of B in C.

(ii) Using virtual is somewhat similar to using Abstract in Java (i think). Now given this, it would mean that there would not be multiple copies of B in C, as the instantiation would be cascaded down to the level it is needed. I am not sure how to word my explanation but say B has a function called print() which prints "i am B" and C overrides this function put prints "i am C". If you called print() on C without virtual you end up printing "i am B", using virtual would mean that it would print "i am C".

(iii) My idea here is that Java can use interfaces to avoid the use of multiple inheritance. You can implement multiple interfaces but you can only extend one Class. I'm not sure what else to add here, so any input or relevant resources would be helpful.

0 投票
1 回答
530 浏览

c++ - 如何让 Doxygen 显示菱形继承图

Doxygen 有一个非常简洁的特性,它可以从代码生成继承图。但是,当从具有公共基础的类中使用多重继承时,该图显示了两个单独的基类(即使我使用的是虚拟继承,如基类周围的虚线所示)

在此处输入图像描述

我怎样才能让 Doxygen 情节更像下面的东西。. .

而不是:(就像没有虚拟继承一样)

0 投票
3 回答
178 浏览

c++ - 非 Diamond 类型中的虚拟继承

当一个类继承自同一个基类的 2 个类时,我无法理解为什么虚拟继承在我们没有遇到类似于钻石问题的问题的情况下有用。

当它仍然有用(或什至需要)时,有人可以给我一个例子或解释吗?

谢谢:)

0 投票
3 回答
419 浏览

java - Java 8 中抽象类对接口的偏好

现在,我们知道 Java 8 在接口中引入了默认方法和静态方法。
最初在 Java 中引入接口是为了避免在 C++ 中出现的多继承中 的菱形问题。

但是随着 Java 8 在接口中引入默认方法,现在 Java 也引入了菱形问题,在之前的版本中它避免了这个问题。

默认方法不是强制需要被覆盖的。
但是当使用接口出现菱形问题时,实现这些接口的类必须覆盖默认方法。

所以现在,我的脑海里有三个问题:

  1. 为什么需要有默认方法?
  2. 难道我们不能通过类本身进行多重继承,而不是在接口中使用默认方法吗?
  3. 如果他们必须在 Java 8 中引入它,那么在以前的版本中需要避免钻石问题吗?

任何好的解释或解释的任何链接?

PS我没有在互联网上找到任何包含任何好文章的链接。
他们只是说抽象类给了你更多的具体性。
如,抽象类可以有构造函数,但接口不能。

再说一次,我想知道,如果抽象类更具体,并且可以有构造函数,
而且无论如何Java已经引入了菱形问题,为什么我们现在应该有接口?抽象类作为独立的多重继承难道不够好吗?

0 投票
2 回答
707 浏览

c++ - 钻石继承两次派生 - 构造函数参数不同 - 找不到指定虚拟继承的基

我努力在标题中简洁地描述这个问题,所以如果你理解这个问题并且有一个更好的标题,请推荐。

我已经制作了我的问题的精简版本,它尽可能小,因此所有函数都是内联定义的,所以请原谅,实际代码不是这样的。

这是我的结构:

所以上面,一个简单地跟踪对象是否有效的接口+实现......想象引擎/系统中的所有对象都将派生自这个单一对象。

现在我有一个假设的类,它只是存储一个数字并打印它。它来源于对象。所以“钻石”是完整的。

现在我从基类派生。关于这个派生类要注意的是,我具有与基类相同的构造函数参数(int 值)。

最后我从这个派生类派生。但是,请注意,此类没有任何构造函数参数。相反,这个类在内部应该知道这个例子中的值应该是 15。

我的期望是,当我实例化 derived2 时,它会用值 15 构造 derived1 并将其传递给对象。我希望做到以下几点:

但是当我尝试这个时,我得到:

如果我添加一个空的 base::base 构造函数,那么我最终会得到未定义的 m_value (但无论如何都尝试过)

我似乎遗漏了一些明显的东西......有人可以突出显示吗?