为什么不导出模板化类的函数会覆盖非模板化基类的纯虚函数?

时间:2017-04-16 10:03:40

标签: c++ templates c++14

#include <vector>

class Base
{
public:
    virtual void foo() = 0;
};

template<typename Bar>
class Cloud : public Base
{
public:
    void foo()
    {
    }
};

class Water
{
};

int main()
{
    Cloud<Water> cloud;
    std::vector<Base> stuff;
    stuff.push_back(cloud);
}

以上显示的代码在MSVC 14.1:

上失败
error C2259: 'Base': cannot instantiate abstract class
note: due to following members:
note: 'void Base::foo(void)': is abstract

为什么Base::foo()仍然是抽象的,即使Cloud实现了它呢? 我如何以Cloud仍然来自Base的方式实现此目的,覆盖foo()并保留typename Bar模板?

2 个答案:

答案 0 :(得分:4)

该函数是一个红色鲱鱼:std::vector<Base>Base个对象的向量,因此push_back会尝试从Base构建Cloud<Water>。< / p>

改为使用std::vector<std::unique_ptr<Base>>

答案 1 :(得分:2)

这里的模板只是一种分心 - 它们与您的问题无关。

std::vector<Base>包含Base 个对象,而不是引用,因此如果您尝试向其添加任何派生实例,它将尝试执行切片,尝试实例化{来自传递的Base的{​​1}}。但是,除了不是你想要的之外,这是不可能的,因为由于cloud是一个抽象类,因此不能存在直的Base对象。

你最想要的就是在保持多态行为的同时将对象推向向量。为此,你必须有一个指针的向量到基类,并推送指向元素的指针 - 最有可能在堆上分配,并且有一些处理它们的生命周期的意思。一个简单的(尽管可能不是最优的)解决方案可能是Base和推送用std::vector<std::shared_ptr<Base>>分配的对象。