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

半世苍凉 提交于 2019-12-11 05:27:48

问题


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

回答1:


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



回答2:


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.




回答3:


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*


来源:https://stackoverflow.com/questions/8736923/cast-base-class-pointer-to-one-of-several-possible-derived-type-pointer-based-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!