Short answer
YES, definitively you can.
Long answer:
WARNING: THe following text may hurt children an sensitive OOP integralists. If you feel or retain to be one of such, stay away from this answer: mine your and everyone alse life will be more easier
Let me reveal a secret: STL code is just nothing more than regular C++ code that comes with headers and libraries, exactly like your code can -and most likely- do.
STL authors are just programmer LIKE YOU. They are no special at all respect to the compiler. Thay don't have any superpower towards it. They sits on their toilet exacly like you do on yours, to do exactly what you do. Don't over-mistify them.
STL code follows the exact same rules of your own written code: what is overridden will be called instead of the base: always if it is virtual, and only according to the static type of its referring pointer if it is not virtual, like every other piece of C++ code. No more no less.
The important thing is not to subvert design issues respecting the STL name convention and semantics, so that every further usage of your code will not confuse people expectation, including yourself, reading your code after 10 years, not remembering anymore certain decisions.
For example, overriding std::exception::what()
must return an explanatory persistent C string, (like STL documentation say) and not add unexpected other fuzzy actions.
Also, overriding streams or streaming operators shold be done cosidering the entire design (do you really need to override the stream or just the streambuffer or just add a specific facet to the locale it imbued?): In other words, study not just "the class" but the design of all its "world" to properly understand how it works with what is around.
Last, but not least, one of the most controversial aspect are containers and everything not having virtual destructors.
My opinion is that the noise about the "classic OOP rule: Dont' derive what has no virtual destructor" is over-inflated: simply don't expect a cow
to became an horse
just because you place a saddle
on it.
If you need (really really need) a class that manage a sequence of character with the exact same interface of std::string that is able to convert implicitly into an std::string and that has something more, you have two ways:
- do what the good good girls do, embed
std:string
and rewrite all its 112 (yes: they are more than 100) methods with function that do nothing more than calling them and be sure you come still virgin to the marriage with another good good boy programmer's code, or ...
- After discover that this takes about 30 years and you are risking to become 40 y.o. virgin no good good boy programmer is anymore interested in, be more practical, sacrifice your virginity and derive
std::string
. The only thing you will loose is your possibility to marry an integralist. And you can even discover it not necessarily a problem: you're are even staying away from the risk to be killed by him!
The only thing you have to take care is that, being std::string
not polymorphic your derivation will mot make it as such, so don't expect and std::string*
or std::string&
referring yourstring
to call your methods, including the destructor, that is no special respect every other method; it just follow the exact same rules.
But ... hey, if you embed and write a implicit conversion operator you will get exactly that result, no more no less!
The rule is easy: don't make yourself your destructor virtual and don't pretend "OOP substitution principle" to work with something that is not designed for OOP and everything will go right.
With all the OOP integralist requemscant in pacem their eternal sleep, your code will work, while they are still rewriting the 100+ std::string method just to embed it.