我的程序需要一个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
。这是什么交易?
答案 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;
}