问题描述
有谁知道为什么 STL 容器没有虚拟析构函数?
Does anyone know why the STL containers don't have virtual destructors?
据我所知,唯一的好处是:
As far as I can tell, the only benefits are:
- 它将实例的大小减少了一个指针(指向虚拟方法表)和
- 它使破坏和构建速度更快一点.
缺点是以通常的方式对容器进行子类化是不安全的.
The downside is that it's unsafe to subclass the containers in the usual way.
也许我的问题可以改写为为什么 STL 容器的设计不允许继承?"
Perhaps my question could be rephrased "Why weren't STL containers designed to allow for inheritance?"
因为它们不支持继承,所以当人们想要一个需要 STL 功能和少量附加功能的新容器(比如一个专门的构造函数或具有默认值的新访问器)时,人们会坚持以下选择地图,或其他):
Because they don't support inheritance, one is stuck with the following choices when one wants to have a new container that needs the STL functionality plus a small number of additional features (say a specialized constructor or new accessors with default values for a map, or whatever):
- 组合和接口复制:创建一个新模板或类,该模板或类拥有 STL 容器作为私有成员,并且每个 STL 方法都有一个传递内联方法.这与继承一样高效,避免了虚拟方法表的成本(在重要的情况下).不幸的是,STL 容器具有相当广泛的接口,因此这需要多行代码才能完成看似容易的事情.
- 只制作函数:使用裸(可能是模板化的)文件范围的函数,而不是尝试添加成员函数.在某些方面,这可能是一种很好的方法,但是封装的好处却消失了.
- 具有公共 STL 访问权限的组合:让 STL 容器的所有者允许用户访问 STL 容器本身(可能通过访问器进行保护).这需要图书馆编写者最少的编码,但对用户来说不太方便.组合的一大卖点是减少了代码中的耦合,但此解决方案将 STL 容器与所有者容器完全耦合(因为所有者返回一个真正的 STL 容器).
- 编译时多态:编写起来可能有些棘手,需要一些代码体操,并且不适用于所有情况.
- Composition and interface replication: Make a new template or class that owns the STL container as a private member and has one pass-through inline method for each STL method. This is just as performant as inheritance, avoids the cost of a virtual method table (in the cases where that matters). Unfortunately, the STL containers have fairly broad interfaces so this requires many lines of code for something that should seemingly be easy to do.
- Just make functions: Use bare (possibly templated) file-scoped functions instead of trying to add member functions. In some ways this can be a good approach, but the benefits of encapsulation are lost.
- Composition with public STL access: Have the owner of the STL container let users access the STL container itself (perhaps guarded through accessors). This requires the least coding for the library writer, but it's much less convenient for users. One of the big selling points for composition is that you reduce coupling in your code, but this solution fully couples the STL container with the owner container (because the owner returns a true STL container).
- Compile-time polymorphism: Can be somewhat tricky to do write, requires some code gymnastics, and isn't appropriate for all situations.
作为一个附带问题:是否有一种标准安全的方式使用非虚拟析构函数进行子类化(假设我不想覆盖任何方法,只是想添加新方法)?我的印象是,如果没有权力更改定义非虚拟类的代码,就没有通用且安全的方法来做到这一点.
As a side question: is there a standards-safe way of subclassing with non-virtual destructors (let's assume that I don't want to override any methods, just that I want to add new ones)? My impression is that there is no generic and safe way of doing this if one does not have the power to change the code defining the non-virtual class.
编辑 2:
正如@doc 指出的,C++ 11 更高级的using
声明降低了组合成本有点.
As @doc points out, C++ 11's fancier using
declarations lower the cost of composition somewhat.
推荐答案
我想它遵循 C++ 哲学,即不对您不使用的功能付费.根据平台的不同,如果您不关心是否有虚拟析构函数,那么虚拟表的指针可能会付出沉重的代价.
I guess it follows the C++ philosophy of not paying for features that you don't use. Depending on the platform, a pointer for the virtual table could be a hefty price to pay if you don't care about having a virtual destructor.
这篇关于为什么 STL 容器没有虚拟析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!