没有RTTI的dynamic_cast

时间:2018-10-26 18:10:06

标签: c++ c++14 multiple-inheritance rtti dynamic-cast

我的结构如下:

struct managed_object {
  virtual ~managed_object() { }
};

class trait1 {
  public: 
    virtual void myMethod() const = 0;
};

class trait2 {
  public: 
    virtual void myOtherMethod(int x) const = 0;
};

class MyType final : public managed_object, public trait1 {
 ...
};

class MyType2 final : public managed_object, public trait1, public trait2 {
 ...
};

class wrapper {
  private:
    managed_object* ptr;
  public:
    template<typename T> T* object() const { 
      return dynamic_cast<T*>(data.ptr); 
    }
};

所以基本上,我有一个managed_object基类,可以从中继承多个类型。每个子类型都可以从特征的任何组合中继承,它们是final,因此我确定它们在继承方面不会有任何更深的层次。

由于RTTI能够将所有内容粘合在一起,但付出了一定的代价,因此代码可以正常工作

wrapper w = ...
trait* asTrait1 = w.object<trait1>;

将不起作用,因为managed_objecttrait1类型之间没有直接关系。

在我完整的代码中,我已经确定所有dynamic_cast都不会失败,因为我还有其他数据(示例中未显示),这为我提供了RTTI的其他部分所需的某种RTTI。代码。

考虑到这一点,假设我已经知道dynamic_cast,是否有一种通用的模式可以解决 -downcast问题而无需使用MyType和RTTI类是从特定的trait继承吗?我试图找到一个聪明的解决方案,因为它是代码的沉重瓶颈。

2 个答案:

答案 0 :(得分:2)

在没有RTTI的情况下,您不能使用dynamic_cast。除了一些特殊情况。

尽管您可以使用static_castreinterpret_cast(请不要使用),但是如果您弄错了,它就在 you 上-那么您将无法再测试nullptr来查看投射是否成功

答案 1 :(得分:0)

首先,您必须使用static_castreinterpret_cast确实不适合这样做。

但是为了使转换正常工作,您的程序需要知道它的运行方向。我的意思是说,它需要知道从AB的转换路径。如果AB在相同的类层次结构中,这很简单:只需按照所述的类层次结构进行转换。

但是如果您有:

struct C: A, B {};

这是AB之间的唯一关系,static_cast无法得知C(这是RTTI提供的信息),由于AB并没有真正的关联,因此它无法执行转换。

为了提供该路径,您必须使您的程序以某种方式知道它。最简单的方法是模板wrapper

template<typename T>
class wrapper {
  managed_object* ptr;
public:
  template<typename Trait> Trait* object() const { 
    return static_cast<Trait*>(static_cast<T*>(ptr)); 
  }
};

然后:

MyType a;
wrapper<MyType> w{&a};
trait1* asTrait1 = w.object<trait1>(); // OK

请注意,我是在通过首先向下转换为派生类型,然后“向上转换”回特征来准确地说明如何进行强制转换。

关于reinterpret_cast

的注释

如果要从类转换为基类(从MyTypetrait1),dynamic_cast将返回指向派生对象中基类子对象的指针或引用static_cast也可以正确进行此转换)。这意味着返回的指针的值实际上可能与提供的指针的值不同。 reinterpret_cast永远不会对指针值进行此类更改。它只会将传递给它的任何内容重新解释为新类型,这显然是错误的。显而易见的结论是不要使用reinterpret_cast在类层次结构内执行强制转换。