Question

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();
} 
Was it helpful?

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();
}

OTHER TIPS

As noted in the comments, the correct way to handle the situation is by introducing a virtual method and having C++ dispatch the call correctly.

Since you cannot modify the base class, you can insert a new class with the virtual function and derive all the classes from the new class instead.

If you need to replicate this behavior with many functions, possibly ones that are not defined yet and the client code will provide, you can leverage the Visitor pattern. In fact, if you cannot change the base class, you can at least use a Vistior-like technique to keep the tedious typekey checks in a single location and take out the actual operations to separate classes.  This will keep you from having to rewrite the typekey checks should another derivedMember-like function.

I think Using dynamic_cast could solve the issue:

    B* base
    if(Class1* c1 = dynamic_cast<Class1*>(base))
    // it's a Class1*
    else if (Class2* c2 = dynamic_cast<Class2*>(base))
    // it's a Class2*
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top