> You're totally missing the point. As foom pointed out earlier, the case
> that you gave initially doesn't actually leak memory, as an int member
> doesn't require any cleanup to be performed. In order for it to leak
> memory, it needs to be an object of a class that requires cleanup, like
> std::string. And if you add such a member to your struct Bar, you need all
> the plumbing I've shown.
*You* are missing the point. Programming in both C and C++ requires strict adherence to certain conventions to make it practical. In C the convention is to have an alloc_foo() and a free_foo(). In C++, the conventions are more complicated (and numerous), but one of them involves using a base class with a virtual destructor.
> (formally, using delete with a base class pointer that points to an object
> of a derived class yields undefined behaviour (UB) unless the base class's
> destructor is virtual, but the memory is correctly freed in any
> implementation I know of, it's just that the destructor for the additional
> member in Bar isn't run -- which doesn't matter as int doesn't have a
Yes, several things need to come together for the bad behavior to bubble to the surface-- putting "new" on a different line than the declaration of shared_ptr, a non-trivial destructor for Bar, a low-memory condition, and your most important customer attending the demo. Does that make you feel better, or worse?
> Also, your example also exhibits UB as soon as you want to use my_foo as a
> struct Bar* (which ought to be possible since it really does point to a
> struct Bar))
Wrong. There's nothing undefined about the behavior of typecasts in C.
In C, the address of the first data member is always equal to the address of the containing struct. So using my_foo as a struct Foo is fine. If you want to use it as a Bar (downcasting) you must use a typecast.
On a more fundamental level, inheritance is an overused technique. C++ experts like Scott Meyers advocate more use of composition, and less of inheritance. Unfortunately, languages like Java and C++ have the opposite bias, giving you all kinds of fancy syntax for inheritance, but almost none for composition.
For example, composition is the only safe way to extend the standard containers in the STL. (Partly this is because they have non-virtual destructors, and partly because the methods they contain may be implementation-dependent.) But if you try to use composition in this way, you'll have to write a wrapper class by hand that passes through every function call to the contained object. It's a tedious and manual process.