
On Fri, Feb 25, 2005 at 12:45:34PM -0500, christopher diggins wrote:
----- Original Message ----- From: "Daniel James" <daniel@calamity.org.uk> To: <boost@lists.boost.org> Sent: Friday, February 25, 2005 11:16 AM Subject: [boost] Re: Querying usefulness of a macro for inheriting from STLcontainers
christopher diggins wrote: I think publicly inheriting from a class that isn't designed for inheritance is a bad idea. There are type safety problems, non-virtual destructors, slicing etc.
Hi Daniel thanks for the help and suggestions ( and Kevin and Jonathan as well),
I have heard here and there, inheriting from STL container is a "bad idea", but I don't specifically know all the reasons why. I am not an expert in this area (heck or any part of C++ for that matter). Isn't it only bad if someone tries to delete the object using a base class pointer? Could we not
That's one reason, yes. (btw, this is Item 35 in Sutter and Alexandrescu's C++ Coding Standards) It's generally a bad idea to inherit from concrete classes that weren't designed to be inherited from, not just STL containers. In fact, it's generally a bad idea to use public inheritance to model anything except substitutablity. Inheritance creates one of the strngest coupling between two classes you can have, and reducing coupling is usually a good idea. One of my favourite C++ quotes is: [Inlines] are the third most-misused C++ feature (after inheritance and overloading). - Nathan Myers If the class wasn't intended to be a base class it probably doesn't have any protected members, only public and private. If that's the case you don't gain anything by inheriting from it, except the convenience of not havng to declare forwarding functions for all the members - but that's laziness, not good design. By inheriting you _do_ get implicit conversions to the base class, which may not be intentional and may not be safe: void f(const container& c) { container copy(c); // ... } void f(MyCustomContainer& c) { // ... } const MyCustomContainer c; f(c); you probably intended to call the overload taking MyCustomContainer here, but because it requires a const you can't - but instead of an error you get a conversion to base reference, and then the object gets sliced.
prevent that idiom by writing type-casts which force failure upon a pointer cast to the inherited type?
For instance:
public MyCustomContainer : container { operator container*() { throw exception("can not cast to container*"); } ... }
Doesn't this solve the virtual destructor problem?
I don't see how: container* mcc = new MyCustomContainer; delete mcc; No chance for a conversion operator to be invoked here, you never even dereference the pointer, but you invoke undefined behaviour because you don't invoke the right destructor.
Another approach perhaps would be to create inheritable versions of the STL containers which are thin wrappers which simply provide a virtual destructor. Would this not work as well?
If you want to inherit from, say, vector, do you _really_ want _all_ its public member functions?
However what are the other problems of type-safety, slicing(?), etc. to which you allude? I am unfamiliar with them and I am not sure how to go about researching the topic.
Slicing refers to copying the base part of a class only, as in the example above. You pass in a MyCustomContainer, but then copy only a slice of it (the base part). jon -- "You know how dumb the average guy is? Well, mathematically, by definition, half of them are even dumber than that." - J.R. "Bob" Dobbs