2013-05-15 166 views
8

我见过很多例子说明了多继承的危险。为什么钻石死亡而不是死亡三角

的例子是像通常的B类和C延伸A类,d延伸类B和C.

B和C二者覆盖从A的方法,例如说,等于();

然后当调用D.equals();它不知道哪一个从其父应该叫

提供的equals()在D

从我看到的却是没有​​被覆盖,是不是A级在这个例子中多余的?如果我们从这个层次结构中删除A并且只看B和C,如果B和C都有方法equals(),那么当D扩展B和C时,它仍然会有同样的问题,所以它不是真的死亡三角?

我不确定我的假设是否会导致某些其他语言的编译时错误。

希望有人能为我澄清它。

+3

不会让它成为'死亡V' – Craig

+0

我认为这个设计相关问题更适合http://programmers.stackexchange.com/。 –

+0

我认为“钻石”只是说明了B类和C类都扩展了A类,尽管A本身不会造成任何麻烦。 – Janman

回答

1

D extends B and C如果不覆盖方法equals(),其在B和C来实现,没有歧义 - d可以使用B.equals()C.equals()

随着另一方面金刚石结构,如果d调用A.equals()和B和C覆盖它,你不知道哪种方法被调用B.equals()C.equals()

+1

你是说你好像在说什么?如果'B'和'C'中的'equals'方法完全不同,该怎么办?如果'D'可以使用'B'或者''C'',那么在我看来,这是一种模糊性。应该选择哪一个? – paxdiablo

+0

我的意思是从执行的角度来看没有歧义。 –

+0

好吧,现在你已经失去了我。如果'B.equals()'返回一个体面的值,'C.equals()'也返回该值,但格式化硬盘后,'D.equals()'应该做什么?无论如何,这似乎是一个骗局,所以它可能应该被关闭。 – paxdiablo

0

你说得对,没有必要存在A来显示多重继承的问题。

下面的代码(如克雷格雄辩地把它放在一个评论“死亡V”)就足够了:

#include <iostream> 

class xyzzy { 
    public: virtual int get (void) { return 7; } 
}; 

class plugh { 
    public: virtual int get (void) { return 42; } 
}; 

class twisty: public xyzzy, public plugh { 
}; 

int main() { 
    twisty passages; 
    std::cout << passages.get() << '\n'; 
    return 0; 
} 

如果您尝试进行编译,您可以:

testprog.cpp: In function ‘int main()’: 
testprog.cpp:16:24: error: request for member ‘get’ is ambiguous 
testprog.cpp:8:14: error: candidates are: virtual int plugh::get() 
testprog.cpp:4:14: error:     virtual int xyzzy::get() 

不过,请记住,您可以明确选择你想要的东西类似于:

std::cout << passages.plugh::get() << '\n'; 

关于钻石问题here的更多信息,包括为什么它实际上是一个不同的问题。

+0

由于显式调用语法'passages.xyzzy :: get()'存在,所以人们称它为“死亡”,这很奇怪,并且让你的意图变得明显。 – nurettin

+0

我认为我现在理解得更好,我认为这会导致编译错误,因为钻石示例不会导致编译错误,但会导致运行时错误? – grumpynerd