dynamic_cast without RTTI

dynamic_cast without RTTI

本文关键字:RTTI without cast dynamic      更新时间:2023-10-16

我有如下结构:

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>;

由于CCD_ 3和CCD_ 4类型之间没有直接关系。

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

假设我已经知道MyType类是从特定的trait继承的,那么在不使用dynamic_cast和RTTI的情况下,是否有一种通用模式可以解决-下变频问题?我正试图找到一个聪明的解决方案,因为这是一个严重的代码瓶颈。

如果没有RTTI,就不能使用dynamic_cast。除了几个角落的箱子。

可以使用static_castreinterpret_cast(请不要(,但如果你弄错了,它就在-然后你就不能再测试nullptr来查看演员是否成功

首先:您必须使用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将返回指向派生对象中基类子对象的指针或引用(managed_object0也可以正确进行此转换(。这意味着返回的指针的值实际上可能不同于提供的指针的数值。CCD_ 31将永远不会对指针值进行这样的改变。它只会将传递给它的东西重新解释为新类型,这显然是错误的。显而易见的结论是不要使用reinterpret_cast在类层次结构中执行强制转换。