这可能已经有了答案,但是我无法找到我尝试的确切情况。

假设您有一些类似于此类的通用变体类(省略了无关的细节):

/* in hpp file */
struct Base {
    void * data;
    Base();
    virtual ~Base();
    // ...
    virtual bool Read(...);
}

template <Some_Enum_Class T>
struct Derived : Base {
    // T-specific interface to deal with Base::data
    bool Read(...); /* implementation in separate cpp file */
}


出于项目的特定原因,此类变体类型可能会引用表示此相同变体类型的集合的容器。也就是说,某些Derived中的void *数据将存储定义良好的类型,并且这些类型最终可能导致Derived的另一个变体,并且不知道哪些提前数据(在编译期间将不可能)必须是无效的*。

Base必要时跟踪T是可以接受的,并且可以将其设置为Derived构造函数中的实例常量。

我不确定在创建Derived实例并将其(作为Base *)存储在void *中之后会发生什么。

如果我将void *并将其转换为Base *(因为我将无法在运行时获取类型信息,也不想超出此处已发生的情况),尽管调用Read之类的函数会正确使用Derived版本编译器无法确定T是多少的事实?

在代码中:

Derived <1> * D = new Derived <1>;
Base * B = (Base*) D; // c-cast for brevity unless this is part of the answer
SendAsVoidPtr( (void*) B ); // at this point the type information is lost


然后再

void * arg = ReceiveVoidPtr();
Base * B = (Base*) arg;
Base->Read(...); // which version does this call and why?


我猜(希望)vtable仅取决于地址(如void *或Base *),因此尽管编译器(可能)无法执行,但它应该可以正常工作并调用Derived :: Read()函数以便提前确定类型,但是我想确定在此结构之上构建之前...

最佳答案

指向vtable的指针实际上是Base中的一个隐藏实例成员(在大多数实现中),因此,是的,您将能够调用Read和其他虚拟函数的正确替代。

10-01 20:10
查看更多