为什么我应该避免C ++中的多重继承? [英] Why should I avoid multiple inheritance in C++?

查看:122
本文介绍了为什么我应该避免C ++中的多重继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解决方案

多继承(缩写为MI),这意味着通常是因为糟糕的原因,并且在面对维护者的时候会被吹回。



摘要




  1. 考虑组合功能而不是继承


  2. 考虑继承多个接口而不是对象

  3. 有时,多重继承是正确的。

  4. $ b $



  5. 准备在代码审查中保护您的多重继承架构
  6. b

    1。也许是组合?



    这是继承的真实情况,因此,对于多重继承更是如此。



    你的对象真的需要继承另一个吗?汽车不需要从引擎继承工作,也不需要从车轮。



    如果你使用多继承来解决这个问题,而不是组合,那么你做错了。



    2。恐惧钻石



    通常,你有一个类A,然后B和C都继承自A.不要问我为什么,有人然后决定D必须继承B和C。



    我在8年中遇到过两次这样的问题,很高兴看到,因为:


    1. 从一开始就有多少错误(在这两种情况下,D都不应该继承自B和C),因为这是糟糕的架构,C根本不应该存在...)

    2. 维护者为此付出了多少钱,因为在C ++中,父类A在其孙代类D中出现了两次,因此,更新一个父字段A ::字段意味着更新它们两次(通过B ::字段和C ::字段),或者有一些默默地错误和崩溃,后来(新的B ::字段中的指针,并删除C :: field ...)

    在C ++中使用虚拟关键字void使上述双重布局无效,做一些错误...



    在对象层次结构中,你应该保持树状结构(一个节点有一个父节点),而不是一个图形。



    3。接口



    多个继承零或一个具体classe,零个或多个接口通常是Ok,因为你不会遇到上述的钻石之恐惧。事实上,这是在Java中做的事情。



    通常,当C从A和B继承时,用户可以使用C,就像它是一个接口是一个抽象类,它具有:







    $ b b


    1. 所有其方法声明为纯虚拟(后缀为= 0)

    2. 没有成员变量

    零到一个真实对象的多重继承,零个或多个接口不被认为是有臭味的(至少不是那么多)



    4。你真的需要多重继承吗?



    有时是的。



    通常,你的C类继承自A和B,A和B是两个不相关的对象(即不在同一层次结构中,没有什么共同点,不同的概念等)。



    具有具有X,Y,Z坐标的节点系统,能够进行大量的几何计算(可能是点,几何对象的一部分),并且每个节点是自动代理,能够与其他代理通信。

    也许你已经可以访问两个库,每个库都有自己的命名空间(使用命名空间的另一个原因...但是你使用命名空间,不是吗?),一个是geo 和另一个是ai



    所以你有自己的own :: Node从ai :: Agent和geo :: Point 。



    这是你应该问自己是否不应该使用composition。如果own :: Node真的是一个ai :: Agent和geo :: Point,那么组合就不会做。



    需要多个继承,让你的自己的:: Node根据它们在3D空间中的位置与其他代理进行通信。



    ai :: Agent和geo :: Point完全,完全,完全不相关...这大大降低了多重继承的危险)



    5。那么,我应该进行多重继承吗?



    大多数时候,没有。 MI不是正确的工具,即使它似乎工作。



    但有时,是的。当时,没有什么比MI更好,你不会有钻石恐惧,你的对象真的是它的父亲。



    但是因为MI是臭的,准备在代码评论中保卫你的架构(和保卫它是一件好事,因为如果你不能保卫它,那么你不应该这样做)。


    Is it a good concept to use multiple inheritance or can I do other things instead?

    解决方案

    Multiple inheritance(abbreviated as MI) smells, which means that usually, it was done for bad reasons, and it will blow back in the face of the maintainer.

    Summary

    1. Consider composition of features, instead of inheritance
    2. Be wary of the Diamond of Dread
    3. Consider inheritance of multiple interfaces instead of objects
    4. Sometimes, Multiple Inheritance is the right thing. If it is, then use it.
    5. Be prepared to defend your multiple-inherited architecture in code reviews

    1. Perhaps composition?

    This is true for inheritance, and so, it's even more true for multiple inheritance.

    Does your object really needs to inherit from another? A Car do not need to inherit from an Engine to work, nor from a Wheel. A Car has an Engine and four Wheel.

    If you use multiple inheritance to resolve this problem instead of composition, then you did something wrong.

    2. The Diamond of Dread

    Usually, you have a class A, and then B and C both inherit from A. And don't ask me why, someone then decides that D must inherit both from B and C.

    I encountered this kind of problem twice in 8 eights years, and it is amusing to see because of:

    1. How much a mistake it was from the beginning (In both cases, D should not have inherited from both B anc C), because this was bad architecture (in fact, C should not have existed at all...)
    2. How much maintainers were paying for that, because in C++, the parent class A was present twice in its grandchild class D, and thus, updating one parent field A::field meant either updating them twice (through B::field and C::field), or have something goes silently wrong and crash, later (new a pointer in B::field, and delete C::field...)

    Using the keyword virtual in C++ void the double layout described above, but anyway, you're probably doing something wrong...

    In Object hierarchy, you should keep the hiearchy as a Tree (a node has ONE parent), not as a graph.

    3. Interfaces

    Multiple inheritance of zero or one concrete classe, and zero or more interfaces is usually Ok, because you won't encounter the Diamond of Dread described above. In fact, this is how things are done in Java.

    Usually, what you mean when C inherits from A and B is that users can use C as if it was a A, and/or as if it was a B.

    In C++, an interface is an abstract class which has:

    1. all its method declared pure virtual (suffixed by = 0)
    2. no member variables

    The Multiple inheritance of zero to one real object, and zero or more interfaces is not considered "smelly" (at least, not as much)

    4. Do you really need Multiple Inheritance?

    Sometimes, yes.

    Usually, your C class is inheriting from A and B, and A and B are two unrelated objects (i.e. not in the same hierarchy, nothing in common, different concepts, etc.).

    For example, you could have a system of Nodes with X,Y,Z coordinates, able to do a lot of geometric calculations (perhaps a point, part of geometric objects) and each Node is an Automated Agent, able to communicate with other agents.

    Perhaps you already have access to two libraries, each with its own namespace (another reason to use namespaces... But you use namespaces, don't you?), one being "geo" and the other being "ai"

    So you have your own "own::Node" derive both from "ai::Agent" and "geo::Point".

    This is the moment when you should ask yourself if you should not use composition instead. If "own::Node" is really really both a "ai::Agent" and a "geo::Point", then composition would not do.

    Then you'll need multiple inheritance, having your "own::Node" communicate with other agents according to their position in a 3D space.

    (You'll note that ai::Agent and geo::Point are completely, totally, fully UNRELATED... This drastically reduces the danger of multiple inheritance)

    5. So, should I do Multiple Inheritance?

    Most of the time, no. MI is not the right tool, even if it seems to work.

    But sometimes, yes. And at that time, nothing will work better than MI, and you won't have a Diamond of Dread, and your object is really both its parent.

    But because MI is smelly, be prepared to defend your architecture in code reviews (and defending it is a good thing, because if you're not able to defend it, then you should not do it).

    这篇关于为什么我应该避免C ++中的多重继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆