多态性:非模板化的基类与模板化的派生类,使用基指针

polymorphism: non-templated base with templated derived class, using base pointer

本文关键字:指针 基类 多态性 派生      更新时间:2023-10-16

这可能已经有一个答案,但我还没有能够找到一个确切的情况下,我正在尝试。

假设您有一些类似于这样的泛型变体类(不相关的细节省略):

/* 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*数据将存储定义良好的类型,这些类型最终可能会导致派生的另一个变体,并且不知道哪些数据必须是void*(在编译期间不可能)。

如果必要的话,Base可以跟踪T,并且可以将其设置为派生构造函数中的实例常量。

我不确定的是,在我创建一个派生的实例并将其存储(作为Base*)在void*中会发生什么。

如果我采取void*并将其转换为Base*(因为我将无法从运行时获取类型信息,也不想超出这里已经发生的事情),调用函数(如Read)是否会正确使用派生版本,尽管编译器无法确定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?

我猜(希望)虚函数表只依赖于地址(作为void*或Base*),所以这应该可以正常工作,并调用Derived<1>::Read()函数,尽管编译器(可能)无法提前确定类型,但我想确定在此结构之上构建之前…

指向vtable的指针本质上是Base中隐藏的实例成员(在大多数实现中),所以是的,您将能够调用Read和其他虚函数的正确覆盖