Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不';STL容器是否具有虚拟析构函数?_C++_Stl_Destructor - Fatal编程技术网

C++ 为什么不';STL容器是否具有虚拟析构函数?

C++ 为什么不';STL容器是否具有虚拟析构函数?,c++,stl,destructor,C++,Stl,Destructor,有人知道为什么STL容器没有虚拟析构函数吗 据我所知,唯一的好处是: 它将实例的大小减少一个指针(指向虚拟方法表)并 它使破坏和建设稍微快一点 缺点是以通常的方式对容器进行子类化是不安全的 编辑: 也许我的问题可以重新表述为“为什么STL容器的设计不允许继承?” 因为它们不支持继承,当一个人想要拥有一个需要STL功能和少量附加功能的新容器时(比如一个专门的构造函数或一个映射的默认值的新访问器,或者其他什么),他就不得不选择以下选项: 组合和接口复制:创建一个新模板或类,该模板或类作为私有成

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

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

  • 它将实例的大小减少一个指针(指向虚拟方法表)并
  • 它使破坏和建设稍微快一点
缺点是以通常的方式对容器进行子类化是不安全的

编辑: 也许我的问题可以重新表述为“为什么STL容器的设计不允许继承?”

因为它们不支持继承,当一个人想要拥有一个需要STL功能和少量附加功能的新容器时(比如一个专门的构造函数或一个映射的默认值的新访问器,或者其他什么),他就不得不选择以下选项:

  • 组合和接口复制:创建一个新模板或类,该模板或类作为私有成员拥有STL容器,并且每个STL方法都有一个直通内联方法。这与继承的性能一样,避免了虚拟方法表的成本(在重要的情况下)。不幸的是,STL容器有相当广泛的接口,因此这需要许多行代码来完成一些看似容易的事情
  • 只创建函数:使用裸的(可能是模板化的)文件作用域函数,而不是尝试添加成员函数。在某些方面,这可能是一种很好的方法,但是封装的好处已经失去了
  • 使用公共STL访问组合:让STL容器的所有者允许用户访问STL容器本身(可能通过访问器进行保护)。对于库编写器来说,这需要最少的编码,但对用户来说却不太方便。组合的一大卖点是减少代码中的耦合,但此解决方案将STL容器与所有者容器完全耦合(因为所有者返回真正的STL容器)
  • 编译时多态性:编写时可能有点棘手,需要一些代码练习,并不适合所有情况
作为一个附带问题:是否有一种标准安全的方法可以使用非虚拟析构函数进行子类化(假设我不想覆盖任何方法,只想添加新的方法)?我的印象是,如果一个人没有能力更改定义非虚拟类的代码,那么就没有通用且安全的方法来实现这一点

编辑2:


AS,C++ 11的Fuxer-<代码>使用声明,降低了构图成本。

< P>虚析构函数仅对继承方案有用。STL容器的设计目的不是从中继承(也不是受支持的方案)。因此,它们没有虚拟析构函数

>虚拟析构函数没有阻止类成为正确的子类。

< P>我猜想这是遵循C++哲学的,即不为不使用的特性付费。根据平台的不同,如果你不在乎虚拟析构函数,那么虚拟表的指针可能是一个巨大的代价。

我认为斯特劳斯特鲁普在他的精彩论文中间接地回答了这个问题:

7闭幕词
是各种各样的吗 上述设施 是否面向对象?哪一个? 使用什么定义 面向对象?在大多数情况下,我 我认为这些问题是错误的。 重要的是你能想出什么主意 清楚地表达,你能有多容易 从不同的角度组合软件 资源,以及效率和效率如何 结果程序的可维护性 是换句话说,你是如何支持的 良好的编程技巧和良好的编程能力 设计技术比设计更重要 标签和流行语。根本 这个想法只是为了改进设计和性能 通过抽象编程。你 要隐藏详细信息,请执行以下操作: 利用系统中的任何共性, 你想让这个价格合理。 我想鼓励你不要这样做 使面向对象成为无意义的 学期“面向对象”的概念 他经常被贬低

–由 把它等同于好,

–通过等值 它使用单一语言,或

–由 接受一切 面向对象的

我认为 有——而且必须有——有用 超越面向对象的技术 编程和设计。但是, 我希望避免被完全误解 我想强调的是,我 不会尝试一个严肃的项目 使用一种编程语言 至少不支持古典音乐 面向对象编程的概念。 除了支持 面向对象编程,我想要—— C++提供的特性 除了那些支持 概念和概念的直接表达 关系


STL的构建主要考虑了三种概念工具泛型编程+函数样式+数据抽象==STL样式。OOP并不是表示数据结构和算法库的最佳方式,这并不奇怪。尽管OOP被用于标准库的其他部分,但STL的设计者发现,上述三种技术的结合比单独使用OOP要好。简而言之,这个库不是用OOP设计的,在C++中,如果你不使用它,它就不会与你的代码捆绑在一起。你不用的东西你不用付钱。类std::vector、std::list、,。。。是Java/C意义上的OOP概念。它们只是最好的解释中的抽象数据类型。

正如已经指出的,STL容器的设计不是为了可继承。没有虚拟方法,所有数据成员都是私有的,没有受保护的getter/setter/helper。。正如你所发现的,没有虚拟析构函数


我建议您确实应该通过组合而不是实现继承来使用容器,以“has-a”的方式而不是“is-a”的方式使用容器。

您不应该盲目地添加虚拟析构函数
 template<typename _Tp, typename _Alloc = allocator<_Tp> >
 class vector : protected _Vector_base<_Tp, _Alloc>
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.
};
class Dog {
public:
   ~Dog() {cout << "Dog is destroyed"; }
};

class Yellowdog : public Dog {
public:
   ~Yellowdog() {cout << "Yellow dog destroyed." << endl; }
};


class DogFactory {
public:
   static shared_ptr<Dog> createYellowDog() { 
      return shared_ptr<Yellowdog>(new Yellowdog()); 
   }    
};

int main() {
    shared_ptr<Dog> pd = DogFactory::createYellowDog();

    return 0;
}
#include <vector>
#include <iostream>

using namespace std;

class Test
{
    int val;
public:
    Test(int val) : val(val)
    {
        cout << "Creating Test " << val << endl;
    }
    Test(const Test& other) : val(other.val)
    {
        cout << "Creating copy of Test " << val << endl;
    }
    ~Test()
    {
        cout << "Destructing Test " << val << endl;
    }
};

class BaseVector : public vector<Test>
{
public:
    BaseVector()
    {
        cout << "Creating BaseVector" << endl;
    }
    virtual ~BaseVector()
    {
        cout << "Destructing BaseVector" << endl;
    }
};

class FooVector : public BaseVector
{
public:
    FooVector()
    {
        cout << "Creating FooVector" << endl;
    }
    virtual ~FooVector()
    {
        cout << "Destructing FooVector" << endl;
    }
};

int main()
{
    BaseVector* ptr = new FooVector();
    ptr->push_back(Test(1));
    delete ptr;

    return 0;
}
Creating BaseVector
Creating FooVector
Creating Test 1
Creating copy of Test 1
Destructing Test 1
Destructing FooVector
Destructing BaseVector
Destructing Test 1