【发布时间】:2020-10-07 03:37:02
【问题描述】:
目前我正在尝试理解 MI 的“邪恶”。我刚刚在 youtube 上观看了一个视频,其中一个 js 家伙反对继承。这是他的例子(我已经用 C++ 重写了):
struct Robot
{ void drive(); };
struct MurderRobot : public Robot
{ void kill(); };
struct CleanerRobot : public Robot
{ void clean(); };
struct Animal
{ void poop(); };
struct Dog : public Animal
{ void bark(); };
struct Cat : public Animal
{ void meow(); };
然后他建议了一个新类MurderRobotDog,在他看来,这不能通过继承来优雅地完成。当然,它不能通过单继承来完成。但我认为用 MI 做这件事没有任何问题。
我认为我们可以创建一个基类BarkingObject,它会包含所有吠叫的东西。然后 Dog 继承自 Animal ,它具有共同的 poop() 和 BarkingObject。而当你需要一个杀狗机器人时,它必须从BarkingObject 和MurderRobot 继承。这更有意义。 MurderRobotDog 不能从活的生物继承,因为这样它就会变成活的,这与机器人的定义相矛盾。当然,为此您必须使用被许多人认为是 EVIL 的多重继承。不幸的是,如果没有它,我们似乎无法有效地重用不同的不相关(你不需要 poop() 来进行 bark(),并且机器人案例证实了这个断言)功能。
你反对我的建议的理由是什么?
【问题讨论】:
-
当然你可以用多重继承写一个
MurderRobotDog。多重继承的问题不在于它是“邪恶的”,问题在于它带来了当你不使用它时根本没有的并发症 -
它甚至不是多重继承使事情变得复杂,而是常见的基础和名称冲突。除非这种设计有特定原因,否则请避免它。在一些其他玩具示例的背景下谈论这个是没有意义的。
-
@OleksijPlotnyc'kyj 首先,是的。你知道虚拟继承吗?只是另一个需要推理和决定的维度。最好让事情尽可能简单。这并不意味着 MI 本质上是邪恶的。如果它在你的设计中有意义,那就去吧。例如,我认为 iostreams 是一个非常有意义的示例。
-
fwiw,称某事为“邪恶”从未帮助任何人。著名的“goto is evil”是一个错误的引述,原标题是“go to statement被认为有害”,并附有对为什么它被认为有害的深入解释。您需要知道为什么不使用它以及有什么缺点,只有这样您才能做出有根据的决定是否使用它。我的建议:不要相信任何称某事为“邪恶”的人
-
“如果没有它,我们将无法有效地重用 [...] 功能 [MI]” - 看起来更像是想象力的失败,而不是事实陈述。此外,我不确定从多个基类继承一堆杂乱且可能相互冲突的东西,而不是包含它们并明确给定名称/行为的来源有什么效率。
标签: c++ class oop inheritance multiple-inheritance