为什么STL容器没有虚拟析构函数?

Mr *_*ooz 31 c++ destructor stl

有谁知道为什么STL容器没有虚拟析构函数?

据我所知,唯一的好处是:

  • 它通过一个指针(到虚拟方法表)减少实例的大小
  • 它使破坏和构造更快一点.

缺点是以通常的方式对容器进行子类化是不安全的.

编辑: 也许我的问题可以改写"为什么不是STL容器设计允许继承?"

因为它们不支持继承,所以当有人想要一个需要STL功能的新容器加上少量的附加功能时(例如一个专门的构造函数或带有地图默认值的新访问器),就会遇到以下选择:管他呢):

  • 组合和接口复制:创建一个拥有STL容器作为私有成员的新模板或类,并为每个STL方法提供一个传递内联方法.这与继承一样高效,避免了虚方法表的成本(在重要的情况下).不幸的是,STL容器具有相当广泛的接口,因此这需要许多代码行,这看起来应该很容易.
  • 只需创建函数:使用裸(可能是模板化的)文件范围的函数,而不是尝试添加成员函数.在某些方面,这可能是一个很好的方法,但封装的好处将丢失.
  • 具有公共STL访问权限的组合:让STL容器的所有者允许用户访问STL容器本身(可能通过访问者保护).这需要编写库编写器的编码最少,但对用户来说却不太方便.一个用于组成的大卖点之一是,你减少代码耦合,但这种方法完全夫妇与业主容器STL容器(因为业主返回一个真正的STL容器).
  • 编译时多态性:编写可能有些棘手,需要一些代码体操,并不适合所有情况.

作为一个附带问题:是否存在一种使用非虚拟析构函数进行子类化的标准安全方法(让我们假设我不想覆盖任何方法,只是我想添加新方法)?我的印象是,如果没有能力更改定义非虚拟类的代码,则没有通用且安全的方法.

编辑2:

正如@doc所指出的那样,C++ 11的发言人using声明在一定程度上降低了作曲的成本.

Jar*_*Par 30

虚拟析构函数仅对继承方案有用.STL容器不是为继承而设计的(也不是受支持的方案).因此他们没有虚拟析构函数.

  • 我从访问者那里发现的一件事是,大多数程序员似乎并没有意识到继承必须由基类设计.当人们意识到"它没有虚拟的析构函数,因为我不应该继承它时,很高兴看到灯泡亮起来." (6认同)
  • 您能否请求STL容器不是为继承而设计的声明? (4认同)
  • @JaredPar,你的回答并没有说明*为什么*. (2认同)

Ara*_*raK 17

我认为Stroustrup在他的精彩论文中间接回答了这个问题:为什么C++不仅仅是面向对象的编程语言:

7结束语备注
上述各种设施是否面向对象?哪个?使用面向对象的定义?在大多数情况下,我认为这些都是错误的问题.重要的是您可以清楚地表达哪些想法,如何轻松地组合来自不同来源的软件,以及所得到的程序的效率和可维护性.换句话说,如何支持良好的编程技术和良好的设计技术比标签和流行语更重要.基本思想只是通过抽象来改进设计和编程.您希望隐藏详细信息,希望利用系统中的任何通用性,并且希望实现这一目标.我想鼓励你不要让面向对象成为无意义的术语."面向对象"的概念经常被贬低

- 把它等同于好,

- 将其等同于单一语言,或

- 接受一切以面向对象的方式.

我认为除了面向对象的编程和设计之外,还有 - 而且必须是 - 有用的技术.然而,为了避免被完全误解了,我想强调的是,使用一种编程语言,没有至少支持面向对象编程的经典概念,我不会试图严重的项目.除了支持面向对象编程的工具之外,我希望 - 和C++提供 - 超出支持直接表达概念和关系的功能.

STL主要是以三个概念工具为基础构建的.通用编程+功能样式+数据抽象== STL样式.OOP并不是表示数据结构和算法库的最佳方式,这并不奇怪.虽然OOP用于标准库的其他部分,但STL的设计者发现,上述三种技术的组合比单独使用 OOP要好.简而言之,该库不是为OOP而设计的,而在C++中如果不使用它,它就不会与您的代码捆绑在一起.你不支付你不使用的东西.类std :: vector,std :: list,... 不是 Java/C#意义上的OOP概念.它们只是抽象数据类型中的最佳解释.

  • 详细而有些偏离主题的答案. (7认同)
  • 真正的问题是他们为什么*需要*他们?!他们没有. (5认同)
  • 我认为这个答案肯定需要修改以更正 Stroustrup 文章的名称:Why C++ is not ** just an ** Object-Oriented Programming Language。 (2认同)

Jim*_*uck 12

我想它遵循C++的理念,即不支付你不使用的功能.根据平台的不同,如果您不关心虚拟析构函数,虚拟表的指针可能需要付出沉重的代价.


doc*_*doc 7

为什么STL容器不能设计为允许继承?

以我的拙见,他们是.如果他们不这样做,那么他们就是最终的.当我查看stl_vector.h源代码时,我可以看到我的STL实现使用受保护的继承_Vector_base<_Tp, _Alloc>来为派生类授予访问权限:

 template<typename _Tp, typename _Alloc = allocator<_Tp> >
 class vector : protected _Vector_base<_Tp, _Alloc>
Run Code Online (Sandbox Code Playgroud)

如果不欢迎子类化,它会不会使用私有继承?


是否有一种标准安全的子类与非虚拟析构函数的方式(让我们假设我不想覆盖任何方法,只是我想添加新的方法)?

为什么不使用protectedprivate继承并使用using关键字公开所需的接口部分?

class MyVector : private std::vector<int>
{
     typedef std::vector<int> Parent;

     public:
        using Parent::size;
        using Parent::push_back;
        using Parent::clear;
        //and so on + of course required ctors, dtors and operators.
};
Run Code Online (Sandbox Code Playgroud)

这种方法可以确保类的用户不会将实例转发给std::vector<int>他并且他是安全的,因为非虚拟析构函数的唯一问题是,当对象作为父类的实例被删除时,它不会调用派生的析构函数.

...我也有一个宽松的想法,如果你的班级没有析构函数,你甚至可以公开继承.异端?

  • 来自 STL 的创建者 Alexander Stepanov http://www.stlport.org/resources/StepanovUSA.html “是的。STL 不是面向对象的。我认为面向对象几乎和人工智能一样是一个骗局。我还没有看看这些 OO 人写的一段有趣的代码。” (2认同)