C++ - 在不使用RTTI/dynamic_cast的情况下向下转换钻石形状的继承对象

Ada*_*dam 14 c++ casting multiple-inheritance rtti diamond-problem

我目前正致力于在非RTTI平台(Android)上集成使用大量RTTI内容的第三方软件包.基本上,我做了自己的RTTI实现,但我遇到了问题.

问题是很多类都有钻石继承问题,因为所有类派生自相同的基类(对象)..所以,如果我想从基类转发到派生类,我必须使用一个dynamic_cast - 但RTTI不可用!当没有dynamic_cast的虚拟继承时,如何将对象从父对象转换为子对象?

它看起来像这样:

class A 
{
public:
 virtual char* func() { return "A"; };
};
class B : public virtual A
{
public:
 //virtual char* func() { return "B"; };
};
class C : public virtual A 
{
public:
 //virtual char* func() { return "C"; };
};

class D : public B, public C 
{
public:
 //virtual char* func() { return "D"; };
};

D d;
A* pa = static_cast<A*>(&d);
D* pd = static_cast<D*>(pa); // can't do that! dynamic_cast does work though...
Run Code Online (Sandbox Code Playgroud)

这些是我的错误:

错误C2635:无法将'A*'转换为'D*'; 隐含了从虚拟基类的转换

错误C2440:'初始化':无法从'test_convert :: A*'转换为'test_convert :: D*'从基础转换为派生需要dynamic_cast或static_cast

有任何想法吗?

CB *_*ley 12

你只能这样做dynamic_cast; 没有其他演员会这样做.

如果您无法设计接口以便不需要执行此类型的强制转换,那么您唯一能做的就是使强制转换功能成为类层次结构的一部分.

例如(可怕的hacky)

class D;

class A
{
public:
    virtual D* GetDPtr() { return 0; }
};

class B : public virtual A
{
};

class C : public virtual A 
{
};

class D : public B, public C 
{
public:
    virtual D* GetDPtr() { return this; }
};
Run Code Online (Sandbox Code Playgroud)

  • 我不知道是否减去或添加这个答案. (3认同)
  • @Noah:在我的辩护中,我确实说过"可怕的hacky"! (2认同)
  • @Noah:hacky版本看起来比我很久以前在一个项目中看到的投射矩阵好.在非rtti-less系统中,人们发现没有什么比给每个类一个唯一的id更好,并使用id作为二维矩阵的索引.matrix [cast_what] [cast_to]是类的id,dynamic_cast的结果. (2认同)

Jan*_*dec 5

Android 确实支持RTTI.您需要最新的NDK(至少r5,最新版本是r6),您需要针对GNU stdlibc ++而不是默认编译.

甚至之前,还有CrystaX的重建支持例外和rtti(我们必须使用它直到官方NDK r5c,因为r5a和r5b有支持,但在旧的(2.3之前的版本)系统崩溃).

PS:有人应该真的禁止供应商说他们支持C++而不支持异常和rtti,因为大多数标准库,以及C++标准的一部分,如果没有,也无法工作.另外,不支持它们是愚蠢的,特别是对于例外,因为具有异常的代码比没有异常的代码更有效(前提是它们被恰当地用于表示异常情况).