如何创建一个模板参数是抽象基类的队列?

时间:2017-10-24 01:34:45

标签: c++ c++11 queue abstract-class

我的程序需要一个FIFO队列来保存所有这些事件。这些事件应该是不同的用户定义类型,但队列需要一个模板参数。所以我想我会使用抽象基类。此外,这还有强制派生类具有我想要的功能签名的好处。

但是,当我尝试以下操作时,我通过std::queue::front检查队列的元素,但它不允许我调用这些元素的虚函数。

#include <iostream>
#include <queue>

class Base
{
public:
    virtual double returnNum() {};
};

class InfoChunk : public Base
{
private:
    double m_num;
public:
    InfoChunk(const double& arg) : m_num(arg) {};
    double returnNum() {return m_num;};
};

int main(int argc, char **argv)
{

    std::queue<Base> q;
    InfoChunk info(.2);
    q.push(info);
    while(!q.empty()){
        std::cout << q.front().returnNum() << "\n";
        q.pop();
    }    

    return 0;
}

这全部编译,但它打印0而不是.2。这是什么交易?

1 个答案:

答案 0 :(得分:1)

要使你的基础是抽象的,它至少需要纯虚函数。此外,您编写代码的原因是因为Base是可切片的。这意味着当派生赋值给base时,派生部分会丢失,因为默认情况下只复制base的成员。

要实现你想要的,你需要使用指针队列(因为派生指针自动转换为基本指针 - 多态兼容),最好是像shared_ptr这样的智能指针,它已经为你执行了必要的内存管理。 / p>

以下示例代码可实现您的目标。

#include <queue>
#include <memory>

struct Base
{
  virtual void foo() = 0;
  virtual ~Base(){}
};

struct Derived : Base
{
  void foo() override{}
};

int main() {

    std::queue<std::shared_ptr<Base>> xq;
    xq.push(std::make_shared<Derived>());
    Base& x = xq.back();
    xq.pop();
    return 0;
}

您也可以使用普通指针,但这意味着您需要提供自己的内存管理(例如):

int main() {

    std::queue<Base*> xq;
    xq.push(new Derived);
    Base* x = xq.back();
    xq.pop(); //Note: Dont delete before popping...
    delete x; //Or keep it

    return 0;
}