这可能已经有了答案,但是我无法找到我尝试的确切情况。
假设您有一些类似于此类的通用变体类(省略了无关的细节):
/* 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
和其他虚拟函数的正确替代。