From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: March-18-11 11:27 AM On 03/18/2011 05:37 AM, Ted Byers wrote:
From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Emil Dotchevski Wouldn't a protected and non-virtual destructor be more appropriate in that case?
How could a protected, non-virtual destructor be appropriate here at all?
You have a single container of smart pointers to a base class. But the actually instances there represent possibly hundreds of different derived classes, generally with very different storage requirements. These are all objects on the heap, so all were created initially using operator new. Operator delete has thus to be called on each of them, and if the destructor is not virtual, you'd have to cast back to the real UDT in order to delete them. Since they are pointers to the base class, you'd have to try a dynamic cast each to every known UDT in order to get a pointer to the right class in order to properly delete it. Nope. shared_ptr remembers the actual type it was constructed with. It doesn't need a virtual destructor, unless you cast to the base before you create the shared_ptr.
Right. The type for the container would be: std::vector<boost::shared_ptr<base_type> > boost::shared_ptr<base_type> and boost::shared_ptr<derived_type> are two different types. You can't cast from the one to the other without writing code to do it. So, to make one vector containing (smart) pointers to instances of any or all the derived types, you would have to cast the pointers to instances the derived types to the base before you create the shared_ptr. Or is it the case that extra intelligence has been adde to boost::shared_ptr, et al, so that if you create a boost::shared_ptr<base_type>, and pass it a pointer to derived type, it remembers the type of the original pointer (and maintains that memory across copy/assignment), and does the right thing when the object is to be freed? If so, that capability was added after I started using them extensively. But I'd be curious as to why and how that would have been added, and when, when virtual functions acomplish the same thing with no extra effort or pain.
That would be an unmaintainable nightmare that is completely avoidable simply by using a virtual destructor and the combination of pointers to the base class living in shared pointers living in turn in a std::vector. The number of UDTs is huge and continually growing (for the biota portion of the model, there are typically UDTs for genera and species, and since there are so many species on the planet, I will probably not live long enough to see UDTs made for all of them).
Cheers Ted