使用多重inheritance时,如何避免死亡钻石?

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

我知道这意味着什么,但是我可以采取什么措施来避免呢?

一个实际的例子:

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

注意D类是如何从B和Cinheritance的,但是B和C都从Ainheritance。这将导致类A的两个副本被包含在vtable中。

为了解决这个问题,我们需要虚拟inheritance。 这是A类,需要虚拟inheritance。 所以,这将解决这个问题:

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

虚拟inheritance。 这就是它的目的。

我会坚持使用接口的多重inheritance。 虽然有时类的多重inheritance是有吸引力的,但是如果你经常依赖它,它也可能会令人困惑和痛苦。

inheritance是强有力的武器。 只有当你真的需要它时才使用它。 在过去,钻石inheritance是一个标志,我将远远分类,说用户是一个“雇员”,但他们也是一个“小工具的听众”,但也是一个…

在这些情况下,很容易出现多重inheritance问题。

我通过使用作文和指针回到主人解决他们:

之前:

 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; }; 

是的,访问权限是不同的,但是如果你能用这种方法逃避,而不重复代码,那更好,因为它不那么强大。 (当你别无select时,你可以节省电力。)

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

在这个类中,A类的属性在D类中重复了两次,这使得更多的内存使用…所以为了节省内存,我们为存储在Vtable中的类A的所有inheritance属性创build一个虚拟属性。

这个链接将详细回答你的问题:

https://isocpp.org/wiki/faq/multiple-inheritance

那么,可怕的钻石的伟大的事情是,它发生时是一个错误。 避免的最好办法是事先弄清楚你的inheritance结构。 例如,我所从事的一个项目是观众和编辑。 编辑器是Viewers的逻辑子类,但是由于所有Viewers都是子类–TextViewer,ImageViewer等,编辑器不能从Viewer中派生出来,因此允许最终的TextEditor,ImageEditor类避开钻石。

在钻石不可避免的情况下,使用虚拟inheritance。 然而,最大的缺陷是虚拟基地,虚拟基地的构造函数必须由最派生的类来调用,这意味着实际上派生的类无法控制构造函数参数。 另外,一个虚拟基地的存在往往会对通过这个链条施放一个表演/空间的惩罚,尽pipe我不相信除了第一个之外还有更多的惩罚。

此外,如果您明确要使用哪个底座,则可以始终使用钻石。 有时候这是唯一的方法。

我会build议更好的课堂devise。 我确定有一些问题可以通过多重inheritance得到最好的解决,但是先检查一下是否有其他的办法。

如果不是,则使用虚拟function/接口。

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