Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 根据条件将基类指针强制转换为几种可能的派生类型指针之一_C++_Casting_Rtti_Derived Types - Fatal编程技术网

C++ 根据条件将基类指针强制转换为几种可能的派生类型指针之一

C++ 根据条件将基类指针强制转换为几种可能的派生类型指针之一,c++,casting,rtti,derived-types,C++,Casting,Rtti,Derived Types,我有一个基类B和几个派生的模板类D,D,D,等等(所以超过十个) 在我的程序中,我发现一种情况,我知道一个B指针指向一个D专门化的实例。我还有一个标识派生类型的唯一键 因此,我想使用基类指针和唯一类型键调用正确的派生类方法。实际上,我想在几个地方这样做,所以我提出的一个解决方案不仅难看,而且很麻烦 >强>有没有更好的方法访问C++中具有基数指针和唯一关键字的派生类成员?< /强> 我不想/无法修改基类。boost库是一个公平的游戏 这是我的潜在代码,但我不喜欢在需要访问派生成员函数/变量的任

我有一个基类
B
和几个派生的模板类
D
D
D
,等等(所以超过十个)

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

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

<> >强>有没有更好的方法访问C++中具有基数指针和唯一关键字的派生类成员?< /强>

我不想/无法修改基类。boost库是一个公平的游戏

这是我的潜在代码,但我不喜欢在需要访问派生成员函数/变量的任何地方复制它。所有这些都是为了一个成员函数调用

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();
} 
B*bptr=。。。
std::type_info*typekey=。。。
if(typekey==&typeid(D)){
D*dptr=静态铸件(bptr);
dptr->derivedMember();
}else if(typekey==&typeid(D)){
D*dptr=静态铸件(bptr);
dptr->derivedMember();
}else if(typekey==&typeid(D)){
D*dptr=静态铸件(bptr);
dptr->derivedMember();
} 
如果所有的
D::
方法都具有相同的名称“DerivedMember”,并且我假设基类B没有将其声明为虚拟,那么您可以将您的层次结构更改为:

class B { etc. };

template<class T>
class D : public B
{
};
B类{etc};
模板
D类:公共B类
{
};
致:

B类{etc};
丙类:公共乙类
{
虚拟void derivedMember()=0;
};
模板
D类:公共C类
{
公众:
void derivedMember(){etc.};
};
那么你可以:

void f(C* c) /* or take a B* and do: C* c = static_cast<C*>(b); */
{    
  c->derivedMember();
}
void f(C*C)/*或取一个B*并执行:C*C=静态施法(B)*/
{    
c->derivedMember();
}

>P>如注释所述,正确处理此情况的方法是引入<代码>虚拟< /C>方法,并用C++正确调用该调用。p> 由于不能修改基类,因此可以使用虚函数插入新类,并从新类派生所有类


如果您需要用许多函数(可能是尚未定义的函数)复制此行为,并且客户端代码将提供这些函数,那么您可以利用。事实上,如果不能更改基类,那么至少可以使用类似Vistior的技术将繁琐的typekey检查保持在一个位置,并将实际操作转移到单独的类中。这将使您不必在另一个类似函数的情况下重写typekey检查。

我认为使用dynamic\u 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*
B*base
if(类别1*c1=动态施法(基础))
//这是一个班级*
否则如果(类别2*c2=动态施法(基础))
//这是一个2级的*

为什么不让
derivedMember()
成为一个虚拟函数?+1到@KerrekSB,同样,如果derivedMember是D的成员函数(但不是B的),您可以在D和B之间引入一个基类C,将derivedMember添加为虚拟函数。@KerrekSB我看不出在这种情况下使派生成员虚拟会有什么帮助。它们不存在于基类中。我认为引入中间类可能是一种选择。我想我真的希望在现有类关系的情况下,有一些东西能起作用,但我肯定不会坚持这样做。我正在探索在代码中创建中间类的想法@基思你可能是说中产阶级是C类:公共B类,对吧?至少,我不知道可以用相同的名称声明模板类和非模板类。也许你可以…我最喜欢你的解决方案,但发现它有点不完整,所以我编辑了。谢谢。当然,不管怎样,为中间层使用不同的名称更干净。请注意,我看到这实际上是对“瘦模板”模式的一种理解——通常为模板提供一个基类,其中包含不需要模板化的所有内容。
    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*