我的程序需要一个 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/