
on Sat May 05 2007, Jeff Garland <jeff-AT-crystalclearsoftware.com> wrote:
Jonathan Franklin wrote:
For example, GCC has a
warning about a derived class whose base doesn't have a virtual dtor. It's actually *impossible* (not just inefficient or convoluted) to implement is_polymorphic without generating that warning.
Interesting. I'm obviously flaunting my ignorance, but I didn't realize that inheriting from a class sans virtual dtor was ever a Good Thing. I'll have to read up on the issues WRT is_polymorphic.
I find inheriting without virtual functions quite useful. The main reason for the virtual destructor rule goes back to Scott Meyers Effective C++. He points out that if you have Base <-- Derived and you call delete Base* the destructor of Derived is not called. In general, it's hard to ensure your derived classes won't need the destructor called and hence the rule. However, if Derived happens to have a trivial/empty destructor then, really there's no reason to call it.
is_polymorphic doesn't do anything so evil as to invoke UB, because the type created is only used to compute the compile-time value of the is_polymorphic predicate, and is never allocated on the heap or delete'd. Anyway, there are many other legitimate idioms that also don't unvoke UB, such as CRTP. Sometimes the existence of a base class is an implementation detail. The base class isn't documented as such, and there's nothing useful clients can do with it, so they never end up touching anything but the complete object. Inheritance is often a crucial tool in creating lightweight objects that shouldn't have any virtual functions.
As a practical example, my super string 'experiment' uses this technique for interface compatibility with std::string. In one incarnation super_string inherits from std::string, which doesn't have a virtual destructor. Since super_string only adds functions to the type, has no state, and a trivial destructor I don't care that it's not called. So, I have an extended type with functions useful to me, it's backward compatible with the existing type, and no virtual table/destructor is needed.
http://www.crystalclearsoftware.com/libraries/super_string/index.html
As long as you don't tell people a super_string IS-A std::string, you're arguably okay... though even then, they'll still probably end up invoking UB unintentionally. -- Dave Abrahams Boost Consulting www.boost-consulting.com Don't Miss BoostCon 2007! ==> http://www.boostcon.com