使用多重继承时如何避免死亡钻石?

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

我知道这意味着什么,但是我可以采取哪些步骤来避免这种情况?

ilitirit asked 2019-11-15T11:05:58Z
8个解决方案
67 votes

一个实际的例子:

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

请注意,类D是如何从B和C继承的。但是B和C都是从A继承的。这将导致vtable中包含类A的2个副本。

为了解决这个问题,我们需要虚拟继承。 这是A类,实际上需要继承。 因此,这将解决问题:

class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
Mark Ingram answered 2019-11-15T11:06:32Z
14 votes

虚拟继承。 那就是它的目的。

eduffy answered 2019-11-15T11:06:57Z
12 votes

我会坚持只使用接口的多重继承。 尽管类的多重继承有时很有吸引力,但是如果您经常依赖它,也可能会造成混乱和痛苦。

Bob Somers answered 2019-11-15T11:07:21Z
6 votes

继承是强大的武器。 仅在确实需要时使用它。 过去,钻石继承是我要进行分类的一个标志,说用户是“雇员”,但他们也是“小工具侦听器”,也是...

在这些情况下,很容易遇到多个继承问题。

我通过使用组合和指向所有者的指针解决了它们:

之前:

class Employee : public WidgetListener, public LectureAttendee
{
public:
     Employee(int x, int y)
         WidgetListener(x), LectureAttendee(y)
     {}
};

后:

class Employee
{
public:
     Employee(int x, int y)
         : listener(this, x), attendee(this, y)
     {}

     WidgetListener listener;
     LectureAttendee attendee;
};

是的,访问权限是不同的,但是如果您可以采用这种方法而又无需重复代码,那会更好,因为它的功能不那么强大。 (当您别无选择时,可以节省电源。)

answered 2019-11-15T11:08:12Z
3 votes
class A {}; 
class B : public A {}; 
class C : public A {}; 
class D : public B, public C {};

在这种情况下,类A的属性在类D中重复两次,这会占用更多的内存。...因此,为了节省内存,我们为存储在Vtable中的所有类A的继承属性创建了一个虚拟属性。

NItish answered 2019-11-15T11:08:35Z
1 votes

好吧,关于可怕的钻石的伟大之处在于,它发生时是一个错误。 避免的最佳方法是事先弄清楚您的继承结构。 例如,我从事的一个项目有查看器和编辑器。 编辑器是Viewer的逻辑子类,但是由于所有Viewer都是子类-TextViewer,ImageViewer等,因此Editor不派生自Viewer,因此最终的TextEditor和ImageEditor类可以避免出现菱形。

在无法避免的情况下,请使用虚拟继承。 但是,对于虚拟基础,最大的警告是,虚拟基础的构造函数必须由最派生的类调用,这意味着派生的类实际上无法控制构造函数的参数。 此外,虚拟基础的存在往往会在整个链中进行投放时导致性能/空间损失,尽管我认为除了第一个以外,还没有太多损失。

另外,如果您明确要使用哪个基准,则始终可以使用菱形。 有时这是唯一的方法。

coppro answered 2019-11-15T11:09:17Z
0 votes

我建议一个更好的课堂设计。 我敢肯定,通过多重继承可以最好地解决某些问题,但是请先检查是否有另一种方法。

如果不是,请使用虚拟功能/接口。

user17720 answered 2019-11-15T11:09:48Z
0 votes

通过委派使用继承。 然后,这两个类都将指向基A,但是必须实现重定向到A的方法。它的副作用是将A的受保护成员转变为B,C和D中的“私有”成员,但是现在您不必 需要虚拟的,而且您没有钻石。

Lee Louviere answered 2019-11-15T11:10:12Z
translate from https://stackoverflow.com:/questions/137282/how-can-i-avoid-the-diamond-of-death-when-using-multiple-inheritance