考虑以下代码:
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
。