The claim that it is a mistake ever to use a standard C++ container as a base class surprises me.
If it is no abuse of the language to declare ...
// Example A typedef std::vector<double> Rates; typedef std::vector<double> Charges;
... then what, exactly, is the hazard in declaring ...
// Example B class Rates : public std::vector<double> { // ... } ; class Charges: public std::vector<double> { // ... } ;
The positive advantages to B include:
The positive advantages to A include:
Both approaches are superior to using a raw container, because if the implementation changes from vector<double> to vector<float>, there's only one place to change with B and maybe only one place to change with A (it could be more, because someone may have put identical typedef statements in multiple places).
My aim is that this be a specific, answerable question, not a discussion of better or worse practice. Show the worst thing that can happen as a consequence of deriving from a standard container, that would have been prevented by using a typedef instead.
Edit:
Without question, adding a destructor to class Rates or class Charges would be a risk, because std::vector does not declare its destructor as virtual. There is no destructor in the example, and no need for one. Destroying a Rates or Charges object will invoke the base class destructor. There is no need for polymorphism here, either. The challenge is to show something bad happening as a consequence of using derivation instead of a typedef.
Edit:
Consider this use case:
#include <vector> #include <iostream> void kill_it(std::vector<double> *victim) { // user code, knows nothing of Rates or Charges // invokes non-virtual ~std::vector<double>(), then frees the // memory allocated at address victim delete victim ; } typedef std::vector<double> Rates; class Charges: public std::vector<double> { }; int main(int, char **) { std::vector<double> *p1, *p2; p1 = new Rates; p2 = new Charges; // ??? kill_it(p2); kill_it(p1); return 0; }
Is there any possible error that even an arbitrarily hapless user could introduce in the ??? section which will result in a problem with Charges (the derived class), but not with Rates (the typedef)?
In the Microsoft implementation, vector<T> is itself implemented via inheritance. vector<T,A> is a publicly derived from _Vector_Val<T,A> Should containment be preferred?
The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe.
@BjörnPollex Yes! I forgot to mention that.
In C++, STL Unordered Associative Containers provide the unsorted versions of the associative container. Internally, unordered associative containers are implemented as hash table data structures.
The standard containers do not have virtual destructors, thus you cannot handle them polymorphically. If you will not, and everyone who uses your code doesn't, it's not "wrong", per se. However, you are better off using composition anyway, for clarity.
Because you need a virtual destructor and the std containers don't have it. The std containers are not designed to act as base class.
For more information read the article "Why shouldn't we inherit a class from STL classes?"
Guideline
A base class must have:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With