考虑以下代码:

class Base
{
public:
    virtual void* allocate(){ return nullptr; }
};

template <class T> class BaseTemplate : public Base
{
public:
    void* allocate() override { return new T(); }
};

class IntSpecialization : public BaseTemplate<int>
{
};

Base GetSpecialization(const int&){ return IntSpecialization(); }

目标是能够使用模板来实现特化,但仍允许用户使用基类接口(interface)进行工作,例如:
int a;
auto s = GetSpecialization(a);
auto p = s.allocate();

上面的代码不起作用;出于明显的原因,s.allocate()始终返回nullptr

我绝对需要GetSpecialization函数来返回Base非模板类,那么我该如何处理呢?
Base类虚拟方法不能是纯净的,因为否则它将变为抽象,并且将导致GetSpecialization的编译失败。

解决此模式的最佳方法是什么?使用C++ 11吗?
谢谢!

最佳答案

Base GetSpecialization(const int&){ return IntSpecialization(); }

您是上面的IntSpecialization对象slicing。为了使您的代码正常工作,GetSpecialization必须返回Base *Base&。例如,以下将按您的预期工作:
std::unique_ptr<Base> GetSpecialization(const int&)
{
    return std::unique_ptr<Base>(new IntSpecialization());
}

Live demo

为了使以上代码正常工作,您需要在virtual中添加一个Base析构函数。
class Base
{
public:
    virtual void* allocate(){ return nullptr; }
    virtual ~Base() = default;
};

否则,当unique_ptr超出范围时,它将调用delete ptr;,其中ptr的类型为Base *,并且通过基类指针对派生类对象进行多态删除是未定义的行为,除非基类析构函数为virtual

10-04 14:54
查看更多