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

标签 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。这是怎么回事?

最佳答案

为了让你的基础是抽象的,它至少需要纯虚函数。此外,您的代码编译的原因是因为 Base 是可切片的。这意味着当将衍生的分配给基时,由于默认情况下仅复制基的成员,因此衍生部分会丢失。

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

下面的示例代码实现了您想要的。

#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;
}

关于c++ - 如何创建一个模板参数是抽象基类的队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46900869/

相关文章:

python - 队列和多处理

c++ - std::queue front 会将前面的元素移出行外吗?

c++从输出中接收 "-1.#IND"?

c++ - 服务器和客户端之间的同步

c++ - 如果我使用选项 -finit-local-zero 编译 Fortran,则 Fortran <-> C++ 互操作性的 Pb

c++ - 类内部 lambda 和 boost 函数

c++ - 声明一个继承final的类

c++ - 在 C++ 中,我应该几乎总是使用虚拟继承吗?

C++11成员类初始化顺序

java - ActiveMq 队列与服务器