Mar*_*ram 68

一个实际的例子:

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
Run Code Online (Sandbox Code Playgroud)

请注意D类是如何从B&C继承的.但是B&C都继承自A.这将导致Vtable中包含2个A类副本.

要解决这个问题,我们需要虚拟继承.它的A类需要实际上是遗传的.所以,这将解决问题:

class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
Run Code Online (Sandbox Code Playgroud)

  • 这就是范围.或者,您可以使用D类中的"using"语句. (6认同)
  • 这只是避免A在内存中两次,它不会避免Diamond造成的任何问题.见http://tinyurl.com/abtjcb; 你如何实现getDepartment,它总是返回正确的东西?你不能!你的设计有缺陷.见http://tinyurl.com/ccjnk6 (4认同)
  • 这个答案不仅适用于您可以控制的课程吗?如果B和C在其他人提供的库中,或者它们是代码库的一部分,则无法更改此"解决方案"根本不起作用.它也违背了OOP的整个原则,即基类不应该关注派生类,但是由于当天晚些时候添加的某些D类,B和C突然不得不改变. (2认同)

edu*_*ffy 15

虚拟继承.这就是它的用途.

  • 不是一个完整的答案. (4认同)
  • 在继承层次结构中的什么位置? (2认同)

Bob*_*ers 12

我坚持只使用接口的多重继承.虽然类的多重继承有时是有吸引力的,但如果你经常依赖它,它也会让人感到困惑和痛苦.

  • @Arafangion C++确实有接口,尽管它不是Java中的语言结构.相反,它们只是纯虚拟基类. (10认同)
  • 我从未遇到过那些不明白这意味着在这种情况下继承纯抽象类的人 (4认同)

小智 6

继承是一种强大而有力的武器.只有在你真正需要时才使用它.在过去,钻石继承是我在分类方面走得很远的一个标志,说用户是"员工",但他们也是"小工具听众",但也是......

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

我通过使用组合和指针回复所有者来解决它们:

之前:

class Employee : public WidgetListener, public LectureAttendee
{
public:
     Employee(int x, int y)
         WidgetListener(x), LectureAttendee(y)
     {}
};
Run Code Online (Sandbox Code Playgroud)

后:

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

     WidgetListener listener;
     LectureAttendee attendee;
};
Run Code Online (Sandbox Code Playgroud)

是的,访问权限是不同的,但如果您可以摆脱这种方法,而不重复代码,那就更好了,因为它的功能不那么强大.(当你别无选择时,你可以节省电力.)