如何在运行时正确地将指向派生类的void*强制转换为指向基类的void* 我目前正在研究一些代码,这些代码需要在运行时实例化半个任意C++类,这意味着如果用户输入“Cule1”,则将例示 Calp1的新实例。

如何在运行时正确地将指向派生类的void*强制转换为指向基类的void* 我目前正在研究一些代码,这些代码需要在运行时实例化半个任意C++类,这意味着如果用户输入“Cule1”,则将例示 Calp1的新实例。,c++,templates,casting,void-pointers,C++,Templates,Casting,Void Pointers,所有这些都必须以void*形式存储,因为这些类不一定共享任何基类(我也想支持原语,但我目前不支持原语) void*在使用时被转换为正确的类型,但问题在于我还允许它们用作指向基类的指针 e、 g 我需要一种方法来正确地投到底部。显然,如果我的字体易于访问,我可以: void* p = (Base*)(new Derived()); ((Base*)p)->someVirtualFunction(); 这样就不会有问题了 然而,我没有那种容易访问的类型 我确实有一个基础设施: class T

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

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

e、 g

我需要一种方法来正确地投到底部。显然,如果我的字体易于访问,我可以:

void* p = (Base*)(new Derived());
((Base*)p)->someVirtualFunction();
这样就不会有问题了

然而,我没有那种容易访问的类型

我确实有一个基础设施:

class Type {};

template<typename T>
class TypeImpl : public Type {};
但是如果没有虚拟函数模板,我就找不到这样做的方法

至于其他解决方案,我最近的想法可能是某种函数指针hashmap的hashmap,它在
std::type_index
上建立索引,但我也没能让它起作用

这可能吗?如果可能,我该怎么做

编辑以澄清:

我有一个
void*p
指向一个
派生的
我需要将它转换为一个
Base*
(例如,
void*p=new-Derived();

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

我需要像这样的东西: <代码>(Base *)(派生*)P<代码>(或等效C++注解),但我不知道它是哪个派生类。< /P>

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

首先,我建议使用C++的转换,而不是普通的旧的C转换,例如<代码> STATICORCAST ,<代码> RealTytCase,<代码> DycMyCase和它们比C类型强制转换更安全,因为它们只做一件事

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

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

因此,您可以使用类似于
reinterpret\u cast(value)
的方法

有关更多信息,请参阅以下资源:


评论中的讨论指出,最初的问题是运行时方法,而
decltype
是编译时。尽管如此,上面的内容可能是相关的,因此我将添加一些关于运行时方法的想法

< > C++模板系统和类型演绎机制运行在编译时。如果您想在运行时处理动态类型系统(即,用户输入决定使用的类型),则必须使用类似于factory的方法


但是,如果有更好的方法,可能值得考虑。

a
void*
只是一个
void*
,即使您在
void*p=(Base*)(new-Derived())中进行了类似的转换它仍然是一个
void*
。你标题中的问题毫无意义。为什么您认为首先需要使用原始的void指针?(也许这个信息在你的问题的某个地方,但是我必须承认我在中间某个地方迷路了)顺便说一下,我迷路的地方是:“我需要一个正确的方式把它投射到基地。”你没有什么特别的事要做,你可以简单地<代码> Base*PTR=新派生()。代码>。。。不需要任何
void*
。。。我觉得你在解决一个可能根本没有问题的问题时陷入了困境。你能解释一下你到底想通过这个疯狂的角色来实现什么吗?(另请参见)@user463035818是的,
void*
是一个
void*
,但我知道它指向一个内存位置,其中包含一个从
Base
派生的类,我只是不知道具体是哪个派生类(或不是直接派生的)。我使用原始void指针是因为我需要读取具有类名的文本文件并实例化它们,但不知道编译时的类型是什么,事实上,该类型在编译时可能不存在(它是一个库),它可能是在使用此DLL的程序中创建的派生类型。我所知道的唯一可以存储任意类的类型是
void*
,如果这些类型共享相同的基,那么(通常)您不需要知道它们的实际类型。您需要知道的是,它们共享相同的基类,并通过指向BaseType的指针访问它们。如果键入erase type,则检索erased type似乎很奇怪。您可能想对它执行“通用”操作,它可以通过擦除存储。我不确定
重新解释\u cast
是否是我想要的,似乎我可能需要
动态\u cast
。但这两者都不能解决问题。C样式的工作很好,没有一个C++的使用我知道的运行时信息吗?decltype似乎很有希望,我会研究它,看看它是否能让我做我需要的事情。然而,从预期用途的描述来看,我认为OP想要一些不同的东西:“例如,如果用户输入“Class1”,Class1的一个新实例将被实例化。”。在我看来,类型解析需要在运行时完成,因此我认为
decltype
在这里没有帮助。@GPhilo,核心问题是将
派生的*
强制转换为
基*
会更改指针的实际整数值,但将
派生的*
转换为
无效的*
转换为
基本的*
则不会。我似乎无法同时把所有需要的信息都变成一个函数。@ PH-TBH,考虑到您的预期使用,我会考虑从空洞指针中移开,并探索像C++ 17这样的选项。
class Type {};

template<typename T>
class TypeImpl : public Type {};
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));
    }
};