子类/继承标准容器? [英] Subclass/inherit standard containers?

查看:118
本文介绍了子类/继承标准容器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常在Stack Overflow上阅读这个语句。就个人而言,我没有发现任何问题,除非我以多态方式使用它;即我必须使用 virtual 析构函数。

I often read this statements on Stack Overflow. Personally, I don't find any problem with this, unless I am using it in a polymorphic way; i.e. where I have to use virtual destructor.

如果我想扩展/添加标准容器的功能那么什么是比继承一个更好的方法呢?将这些容器包装在自定义类中需要更多的努力,仍然不清楚。

If I want to extend/add the functionality of a standard container then what is a better way than inheriting one? Wrapping those container inside a custom class requires much more effort and is still unclean.

推荐答案

坏主意。

首先,这是一个坏主意,因为标准容器没有虚拟析构。你不应该使用没有虚拟析构函数的多态的东西,因为你不能保证你的派生类中的清理。

First, this is a bad idea because the standard containers do not have virtual destructors. You should never use something polymorphically that does not have virtual destructors, because you cannot guarantee cleanup in your derived class.

虚拟引擎

其次,这真的是糟糕的设计。实际上有几个原因是坏的设计。首先,您应该总是通过一般操作的算法扩展标准容器的功能。这是一个简单的复杂性原因 - 如果你必须为每个容器写一个算法,并且你有M个容器和N个算法,那就是你必须写的M x N个方法。如果你一般写算法,你只有N个算法。所以你得到更多的重用。

Second, it is really bad design. And there are actually several reasons it is bad design. First, you should always extend the functionality of standard containers through algorithms that operate generically. This is a simple complexity reason - if you have to write an algorithm for every container it applies to and you have M containers and N algorithms, that is M x N methods you must write. If you write your algorithms generically, you have N algorithms only. So you get much more reuse.

这也是一个很糟糕的设计,因为你是通过从容器继承打破良好的封装。一个好的经验法则是:如果您可以使用类型的公共接口执行所需的操作,请将该新行为应用于该类型的外部。这改善了封装。如果它是一个你想实现的新行为,使它成为命名空间范围函数(像算法)。如果你有一个新的不变式强制,在类中使用containment。

It is also really bad design because you are breaking a good encapsulation by inheriting from the container. A good rule of thumb is: if you can perform what you need using the public interface of a type, make that new behavior external to the type. This improves encapsulation. If it's a new behavior you want to implement, make it a namespace scope function (like the algorithms). If you have a new invariant to impose, use containment in a class.

封装的经典说明

最后,一般来说,你不应该将继承视为扩展类行为的一种手段。这是早期OOP理论的大,坏的谎言之一是由于对复用的不清楚的想法而产生的,并且它继续被教导和推广到这一天,即使有一个清楚的理论为什么它不好。当您使用继承来扩展行为时,您将以扩展行为绑定到您的接口合约,以使用户接触未来的变化。例如,假设你有一个Socket类型,它使用TCP协议进行通信,并通过从Socket派生一个SSLSocket类并在Socket之上实现更高的SSL栈协议的行为来扩展它的行为。现在,让我们说你有一个新的要求,有相同的通信协议,但通过USB线,或通过电话。您需要将所有工作切割并粘贴到源自USB类或电话类的新类中。现在,如果你发现一个bug,你必须在所有三个地方修复它,这不会总是发生,这意味着bug会花更长的时间,而不是总是得到修复...

Finally, in general, you should never think about inheritance as a means to extend the behavior of a class. This is one of the big, bad lies of early OOP theory that came about due to unclear thinking about reuse, and it continues to be taught and promoted to this day even though there is a clear theory why it is bad. When you use inheritance to extend behavior, you are tying that extended behavior to your interface contract in a way that ties users hands to future changes. For instance, say you have a class of type Socket that communicates using the TCP protocol and you extend it's behavior by deriving a class SSLSocket from Socket and implementing the behavior of the higher SSL stack protocol on top of Socket. Now, let's say you get a new requirement to have the same protocol of communications, but over a USB line, or over telephony. You would need to cut and paste all that work to a new class that derives from a USB class, or a Telephony class. And now, if you find a bug, you have to fix it in all three places, which won't always happen, which means bugs will take longer and not always get fixed...

这是通用的任何继承层次A-> B-> C - > ...当你想使用你在派生类中扩展的行为,如B,C,..对象不是基类A,你必须重新设计或重复实现。这导致非常单片的设计,很难改变的道路(认为微软的MFC,或他们的.NET,或者 - 他们犯了很多错误)。相反,你应该几乎总是认为扩展通过组合只要可能。当你在思考开放/封闭原则时,应该使用继承。你应该有通过继承类的抽象基类和动态多态运行时,每个都将完全实现。层次结构不应该深 - 几乎总是两个层次。只有使用两个以上时,您有不同的动态类别,去到需要区分类型安全的各种功能。在这些情况下,使用抽象基本直到叶类,它有实现。

This is general to any inheritance hierarchy A->B->C->... When you want to use the behaviors you've extended in derived classes, like B, C, .. on objects not of the base class A, you've got to redesign or you are duplicating implementation. This leads to very monolithic designs that are very hard to change down the road (think Microsoft's MFC, or their .NET, or - well, they make this mistake a lot). Instead, you should almost always think of extension through composition whenever possible. Inheritance should be used when you are thinking "Open / Closed Principle". You should have abstract base classes and dynamic polymorphism runtime through inherited class, each will full implementations. Hierarchies shouldn't be deep - almost always two levels. Only use more than two when you have different dynamic categories that go to a variety of functions that need that distinction for type safety. In those cases, use abstract bases until the leaf classes, which have the implementation.

这篇关于子类/继承标准容器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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