Why don't STL containers have virtual destructors?

后端 未结 9 2144
时光取名叫无心
时光取名叫无心 2020-11-28 07:54

Does anyone know why the STL containers don\'t have virtual destructors?

As far as I can tell, the only benefits are:

  • it reduces the size of an insta
相关标签:
9条回答
  • 2020-11-28 08:00

    I think Stroustrup answered this question indirectly in his fantastic paper: Why C++ is not just an ObjectOriented Programming Language:

    7 Closing Remarks
    Are the various facilities presented above objectoriented or not? Which ones? Using what definition of objectoriented? In most contexts, I think these are the wrong questions. What matters is what ideas you can express clearly, how easily you can combine software from different sources, and how efficient and maintainable the resulting programs are. In other words, how you support good programming techniques and good design techniques matters more than labels and buzz words. The fundamental idea is simply to improve design and programming through abstraction. You want to hide details, you want to exploit any commonality in a system, and you want to make this affordable. I would like to encourage you not to make objectoriented a meaningless term. The notion of ‘‘objectoriented’’ is too frequently debased

    – by equating it with good,

    – by equating it with a single language, or

    – by accepting everything as objectoriented.

    I have argued that there are – and must be – useful techniques beyond objectoriented programming and design. However, to avoid being totally misunderstood, I would like to emphasize that I wouldn’t attempt a serious project using a programming language that didn’t at least support the classical notion of objectoriented programming. In addition to facilities that support objectoriented programming, I want – and C++ provides – features that go beyond those in their support for direct expression of concepts and relationships.

    STL was built with three conceptual tools in mind mainly. Generic Programming + Functional Style + Data Abstraction == STL Style. It is not strange that OOP is the not the best way to represent a Data Structure & Algorithms library. Although OOP is used in other parts of the standard library, the designer of STL saw that the mix of the three mentioned techniques is better than OOP alone. In short, the library wasn't designed with OOP in mind, and in C++ if you don't use it, it doesn't get bundled with your code. You don't pay for what you don't use. The classes std::vector, std::list,... are not OOP concepts in the Java/C# sense. They are just Abstract Data Types in the best interpretation.

    0 讨论(0)
  • 2020-11-28 08:02

    A virtual destructor is only useful for inheritance scenarios. STL containers are not designed to be inherited from (nor is it a supported scenario). Hence they don't have virtual destructors.

    0 讨论(0)
  • 2020-11-28 08:04

    As has been pointed out, the STL containers are not designed to be inheritable. No virtual methods, all data members are private, no protected getters/setters/helpers.. And as you've discovered, no virtual destructors..

    I'd suggest you should really be using the containers via composition rather than implementation inheritance, in a "has-a" way rather than an "is-a" one.

    0 讨论(0)
  • 2020-11-28 08:10

    No virtual destructor prevents the class from being subclasses correctly.

    0 讨论(0)
  • 2020-11-28 08:13

    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.

    0 讨论(0)
  • 2020-11-28 08:13

    If you really need virtual destructor, you can add it in class derived from vector<>, and then use this class as a base class everywhere you need virtual interface. By doing this compilator will call virtual destructor from your base class, which in turn will call non-virtual destructor from vector class.

    Example:

    #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;
    }
    

    This code gives following output:

    Creating BaseVector
    Creating FooVector
    Creating Test 1
    Creating copy of Test 1
    Destructing Test 1
    Destructing FooVector
    Destructing BaseVector
    Destructing Test 1
    
    0 讨论(0)
提交回复
热议问题