A former colleague of mine has left a note saying: "Subclassing C++ containers can cause problems, primarily because the container classes were not intended to be subclassed."
Unfortunately, I no longer have contact with that colleague, so I cannot ask him what he meant. Instead I try here.
Is it true that subclassing, for example, std::vector can cause problems and should be avoided? And if so, what kind of problems are we talking about?
Right, well, it would be weird to derive from the class if it wasn't to use it polymorphically. Otherwise, you could have basically the same functionality by keeping it as a member of a different class. Right?
Technically speaking yes. The problem with containment is that if I want to user to access the data
as if it were the underlying STL container, I have to write forwarders for all STL container public
member functions, which sucks.
On the other hand, since the class I'm writing I know is a value class that will never be a base class,
and I know I will never store instances of it by pointer to base class (ie, never delete it polymorphically),
then I can short-circuit having to write all those forwarders by simply deriving from the container.
Now I wouldn't propose doing this everywhere; in my case, the class in question was an adjunct to
another class that I know will never be used elsewhere because it is specifically tied to it.
(The reason for my derivation in the first place was two-fold: first, my class, in addition to the container,
has one other data member, and second, I needed to provide useful constructors to simplify usage.)
Efficiency. Adding virtual methods adds one level of indirection to member function calls. Something along the lines of object.__virtual_table[function](parameter); (I probably screwed up the member function pointer syntax. Don't bother correcting me).
I was reading C++ Gotchas and there is an item about virtual static methods. I know it sounds crazy at first but it wasn't talking about using the keywords together, it was talking about a specific time when that sort of behavior can be achieved. Basically, it stated that member operators new and delete are always static, in that they do not need an instance of the class to be called, and that when a member operator new for a derived class is used I think it said that the standard requires the implementation to call the matching delete, even though a base class pointer. Now, I think I'm missing one other specific about the classes in question--I think this might have only been applicable when the base class did not have a virtual destructor.
If that is true then wouldn't it be possible to safely subclass an STL container as long as you specify the member operators new and delete?
I'll look this up tonight when I get home. I might have misunderstood that item, merged two items into one, etc..
It's more than efficiency (if only the destructor were declared virtual, then only destruction has additional processing
overhead): it's C++'s rule that says you don't pay for what you don't use. The first virtual function incurs the extra
overhead of a virtual table pointer, making the object's memory footprint larger.
Now, I think I'm missing one other specific about the classes in question--I think this might have only been applicable when the base class did not have a virtual destructor.
I looked this up and the virtual static method behavior is only possible when you DO have a virtual base destructor. In that case it has something to do with calling the most specialized operator delete available.