Search code examples
c++rtti

Virtual functions that act like dynamic casts


In JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS Bjarne states, that:

Down casting (casting from base to derived class) shall only be allowed through one of the following mechanism:

  1. Virtual functions that act like dynamic casts (most likely useful in relatively simple cases)
  2. Use of the visitor (or similar) pattern (most likely useful in complicated cases)

I can't wrap my head around first proposition. Googling it presented no examples, nor explanation.

How can virtual function act like a dynamic cast?


Solution

  • It's referring to a technique that was kind of common in the early days of C++, before dynamic_cast, RTTI, etc., were added to the language.

    The basic idea looks something like this:

    class Derived1;
    class Derived2;
    
    class Base {
    public:
        virtual Derived1 *toDerived1() const { return nullptr; }
        virtual Derived2 *toDerivde2() const { return nullptr; }
    };
    
    class Derived1 : public Base { 
    public:
        Derived1 *toDerived1() const override { return this; }
        Derived2 *toDerived2() const override { return nullptr; }
    };
    
    class Derived2 : public Base { 
    public:
        Derived1 *toDerived1() const override { return nullptr; }
        Derived2 *toDerived2() const overrode { return this; }
    };
    

    This lets you do something just about like a dynamic_cast on a pointer, yielding a pointer to the expected type if the pointee object is actually of that type, and otherwise a nullptr.

    This has obvious disadvantages though. Every class involved has to be aware of every other class. Adding a new class means adding a new function to every class. Unless the entire class structure is quite static (and a small number of classes altogether), this can quickly turn into a maintenance nightmare.

    Reference

    This technique was covered in Effective C++, 1st Edition, Item 39. I haven't checked to be sure, but it was probably dropped from the newer editions, as (at least in the minds of most programmers) the addition of dynamic_cast rendered it obsolescent (at best).