如何在运行时正确地将指向派生类的void *强制转换为指向基类的void *

时间:2018-08-08 11:55:07

标签: c++ templates casting void-pointers

我目前正在研究一些需要在运行时实例化半任意c ++类的代码。用户输入“ Class1”,将实例化Class1的新实例。

所有这些都必须以void *形式存储,因为这些类不必共享任何基类(我也想支持基元,但我目前不支持)。

在使用时将void *强制转换为正确的类型,但是问题在于,我还允许它们用作指向基类的指针。

例如

void* p = new Derived();
((Base*)p)->someVirtualFunction();

我需要一种正确投射到基地的方法。显然,如果我拥有易于访问的类型,则可以:

void* p = (Base*)(new Derived());
((Base*)p)->someVirtualFunction();

不会有问题。

但是我没有那种容易使用的类型。

我确实有一个基础架构:

class Type {};

template<typename T>
class TypeImpl : public Type {};

在实际代码中,它们具有许多与手头问题无关的功能。

我可以访问指向Type*的{​​{1}}和指向TypeImpl<Base>的{​​}

我正在尝试找到一种使用这些方法正确投射指针的方法 例如

TypeImpl<Derived>

但没有虚函数模板,我找不到实现此目的的方法。

对于其他解决方案,我最接近的想法可能是某种在class Type { void* cast(Type* type_of_p, void* p)=0; template<typename C> void* castTo(void* p)=0; }; template<typename T> class TypeImpl : public Type { void* cast(Type* type_of_p, void* p){ return type_of_p->castTo<T>(p); } template<typename C> void* castTo(void* p){ return ((C*) ((T*) p)); } }; 上进行索引的函数指针的散列表的散列表,但我也无法使其正常工作。

这有可能吗?如果可以的话,我该怎么做?

编辑以明确声明:

我有一个指向std::type_index的{​​{1}},我需要将其强制转换为void* p (例如Derived

Base*或任何不使用运行时信息的类型转换都无效,因为该vtable未对齐。

我需要类似的东西: void* p = new Derived();(或等效的c ++强制类型转换),但我不知道它是哪个派生类。

我不确定我的措辞是否很差,还是我犯了一些错误,但这是核心问题。

1 个答案:

答案 0 :(得分:1)

首先,我建议使用C ++强制转换,而不要使用普通的旧C强制转换,例如static_castreinterpret_castdynamic_castconst_cast。它们比C型强制转换更安全,因为它们只做一件事。

由于您提到您有一个指向要尝试转换为基类/派生类的对象的指针,因此可以使用decltype

decltype是C ++ 11说明符,它产生作为参数传递的变量的类型。

因此,您可以使用类似reinterpret_cast<decltype(base_pointer)>(value)的东西。

有关更多信息,请查看以下资源:

https://en.cppreference.com/w/cpp/language/decltype

Cast a value using decltype, is it possible?

When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?


评论中的讨论指出,最初的问题要求运行时方法,而decltype是编译时。尽管如此,以上内容可能是有意义的,因此我将对运行时方法添加一些想法。

C ++模板系统和类型推导机制在编译时运行。如果要在运行时处理动态类型系统(即由用户输入确定使用的类型),则必须使用工厂方法。

但是,也许有必要考虑是否有更好的方法。