使用多重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一个虚拟属性。
这个链接将详细回答你的问题:
那么,可怕的钻石的伟大的事情是,它发生时是一个错误。 避免的最好办法是事先弄清楚你的inheritance结构。 例如,我所从事的一个项目是观众和编辑。 编辑器是Viewers的逻辑子类,但是由于所有Viewers都是子类–TextViewer,ImageViewer等,编辑器不能从Viewer中派生出来,因此允许最终的TextEditor,ImageEditor类避开钻石。
在钻石不可避免的情况下,使用虚拟inheritance。 然而,最大的缺陷是虚拟基地,虚拟基地的构造函数必须由最派生的类来调用,这意味着实际上派生的类无法控制构造函数参数。 另外,一个虚拟基地的存在往往会对通过这个链条施放一个表演/空间的惩罚,尽pipe我不相信除了第一个之外还有更多的惩罚。
此外,如果您明确要使用哪个底座,则可以始终使用钻石。 有时候这是唯一的方法。
我会build议更好的课堂devise。 我确定有一些问题可以通过多重inheritance得到最好的解决,但是先检查一下是否有其他的办法。
如果不是,则使用虚拟function/接口。
通过委派使用inheritance。 然后这两个类将指向一个基础A,但必须实现redirect到A的方法。它具有将A的受保护成员转换为B,C和D中的“私有”成员的副作用,但是现在您不需要虚拟的,而你没有钻石。
- 如何在Linux中命名一个线程?
- 为什么试着{…}最后{…}好; 尝试{…} catch {}不好?
- 如何在debugging时将Visual Studioexception消息语言更改为英文
- 如何从文件中删除单个属性(例如ReadOnly)?
- SecurityException:必须将ECall方法打包到系统模块中
- 错误的if语句 – 不能隐式转换types为'布尔'
- 控制台应用程序:每个configuration文件只允许有一个<configSections>元素,如果存在,则必须是根<configuration>元素的第一个子元素
- WPF MVVM:如何closures一个窗口
- 在c#代码中使用c ++ dll中定义的类