基于条件将基类指针转换为几个可能的派生类型指针之一

时间:2012-01-05 02:33:35

标签: c++ casting rtti derived-types

我有一个基类B和几个派生模板类D<int>D<float>D<double>等(超过十个)

在我的程序中,我发现一种情况,我有一个B指针,我知道指向一个D特化的实例之一。我还有一个标识派生类型的唯一键。

所以,我想使用我的基类指针和唯一类型键调用正确的派生类方法。我实际上想在几个地方做这个,所以我想出的一个解决方案不仅难看,而且很麻烦。

有没有更好的方法来访问派生类的成员在C ++中具有基指针和唯一键?

我不想/不能修改基类。提升图书馆是公平的游戏。

这是我的潜在代码,但我不满意在需要访问派生成员函数/变量的任何地方复制它。所有这一切都用于一个成员函数调用?!!

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

3 个答案:

答案 0 :(得分:2)

如果所有D<type>::方法都具有相同的名称'DerivedMember`,并且我假设基类B没有将其声明为虚拟,那么您可以更改您的层次结构:

class B { etc. };

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

为:

class B { etc. };

class C : public B
{
 virtual void derivedMember() = 0;
};


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

然后你可以:

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

答案 1 :(得分:0)

正如评论中所指出的,处理这种情况的正确方法是引入virtual方法并让C ++正确调度调用。

由于无法修改基类,因此可以使用虚函数插入新类,并从新类派生所有类。

如果您需要使用许多函数复制此行为,可能还有尚未定义且客户端代码将提供的函数,您可以利用Visitor pattern。事实上,如果你不能改变基类,你至少可以使用类似Vistior的技术将繁琐的typekey检查保存在一个位置,并取出实际操作来分离类。这将使您不必重写typekey检查另一个derivedMember - 类似函数。

答案 2 :(得分:0)

我认为使用dynamic_cast可以解决问题:

    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*