Does anyone know why the STL containers don\'t have virtual destructors?
As far as I can tell, the only benefits are:
Another solution to be able to subclass from STL containers is one given by Bo Qian using smart pointers.
Advanced C++: Virtual Destructor and Smart Destructor
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;
}
This avoids the dillema with virtual destructors altogether.
Why weren't STL containers designed to allow for inheritance?
In my humble opinion they are. If they wouldn't, they had been made final. And when I look into stl_vector.h
source I can see that my STL implementation uses protected inheritance of _Vector_base<_Tp, _Alloc>
to grant access for derived classes:
template<typename _Tp, typename _Alloc = allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
Wouldn't it use private inheritance if subclassing was not welcome?
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)?
Why not use protected
or private
inheritance and expose desired part of interface with using
keyword?
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.
};
This approach ensures that the user of the class will not downcast instance to std::vector<int>
and he is safe, since the only problem with non-virtual destructor is that it won't call derived one, when object gets deleted as an instance of parent class.
...I have also loose idea, that you may even inherit publicly if your class doesn't have a destructor. Heresy?
you're not supposed to blindly add a virtual destructor to every class. If that were the case, the language wouldn't allow you any other option. When you add a virtual method to a class that doesn't have any other virtual methods, you just increased the size of the class instances by the size of a pointer, typically 4 bytes. That's expensive depending on what you're doing. The size increase happens because a v-table is created to hold the list of virtual methods, and each instance needs a pointer back to the v-table. It's typically located at the first cell of the instance.