Search code examples
c++castingrttiderived-types

cast base class pointer to one of several possible derived type pointer based on condition


I have a base class B and several derived template classes D<int>, D<float>, D<double>, etc. (so more than ten)

In my program, I find a situation where I have a B pointer that I KNOW points to an instance one of the D specializations. I also have a unique key that identifies the derived type.

So, I want to call the correct derived class method using my base class pointer and the unique type key. I actually want to do this in several places, so the one solution I have come up with is not only ugly, but cumbersome.

Is there a better way to access the derived class's members having a base pointer and a unique key in C++?

I don't want to / can't modify the base class. boost library is fair game.

Here is my potential code, but I'm not happy with replicating this everywhere I need to access a derived member function/variable. All of this for one member function call?!!

B * bptr = ...
std::type_info * typekey = ...

if        (typekey == &typeid(D<float>) ) {
    D<float> * dptr = static_cast<D<float>*>(bptr);
    dptr->derivedMember();
} else if (typekey == &typeid(D<double>) ) {
    D<float> * dptr = static_cast<D<double>*>(bptr);
    dptr->derivedMember();
} else if (typekey == &typeid(D<int>) ) {
    D<float> * dptr = static_cast<D<int>*>(bptr);
    dptr->derivedMember();
} 

Solution

  • If all the D<type>:: methods have the same name 'DerivedMember`, and I assume that the base class B does not declare this as virtual, can you change your hierachy from:

    class B { etc. };
    
    template<class T>
    class D : public B
    {
    };
    

    to:

    class B { etc. };
    
    class C : public B
    {
     virtual void derivedMember() = 0;
    };
    
    
    template<class T>
    class D : public C
    {
    public:
    void derivedMember() { etc. };
    };
    

    Then you could have:

    void f(C* c) /* or take a B* and do: C* c = static_cast<C*>(b); */
    {    
      c->derivedMember();
    }