存储具有在容器中继承同一类的不同类型的对象

时间:2014-04-12 19:08:48

标签: c++ qt containers abstract-class

我有以下课程:

class ActivityItem : public QGraphicsItem;
class DeadTimeItem : public QGraphicsItem;

我需要将ActivityItemDeadTimeItem类型的对象存储在同一容器中,以便我可以一起使用它们。

我尝试了什么?

我尝试创建一个存储QVector类型的QGraphicsItem,但我得到的结果是它不能存储抽象类类型。我该怎么办?

我的计划

我的计划是将这些元素存储到类QVector<T>的{​​{1}}成员中,因为它们会创建时间轴。例如:

timeline

我的时间轴应如下图所示:

enter image description here

因此,当用户调用class timeline : public QGraphicsScene // is this a good idea? to inherit QGraphicsScene? { private: QVector<QGraphicsItem*> items; int left_offset; // this is for putting the items next to each other public: timeline(); void add_item( QGraphicsItem *item ); ~timeline(); } 方法时,

add_item()

Timeline *timeline; timeline->add_item( new ActivityItem( /* parameters */ ) ); // timeline->left_offset += 150; timeline->add_item( new DeadTimeItem( /* parameters */ ) ); // timeline->left_offset += 100; 会根据插入项目的类型而增加。

我知道我的帖子很长,但请完整阅读,因为我真的需要你的帮助!谢谢!

正如你已经猜到的那样,我正在使用Qt。如果确实有必要,我也可以使用boost。

2 个答案:

答案 0 :(得分:2)

你不能创建一个抽象类的实例,这是幸运的,因为尝试将派生类分配给基类会以其他有趣的方式引发切片或行为异常。

由于上述限制,base的标准容器不能存储派生的。您可以通过使用指向base的指针来避开此限制,无论是原始(非拥有)指针还是某些智能指针类型。

使用标准库的答案如下:

std::vector<std::shared_pointer<QGraphicsItem>> v;

使用QT课程:

QVector<QSharedPointer<QGraphicsItem>> qv;

答案 1 :(得分:2)

假设

  • QGraphicsItem个对象是同一场景的一部分,并且有一个父
  • 该列表与场景紧密相关(拥有场景的同一个类的成员变量,或场景子类的成员变量)。

然后你应该使用它:

    QList<QGraphicsItem*> items; // or QVector or std::list, nearly same

这些是原始指针,它们不会在从列表中删除时自动删除对象,也不会在删除项目时收到通知。尽管如此,我还不知道智能指针类型,它可以与QGraphicsItem一起使用,所以原始指针是你必须使用的。因此,如果您还需要动态删除项目,请继续阅读:


首先,当您删除项目时,还需要从该列表中删除指针,以避免悬空指针。例如,您可能希望使用类似QList::indexOf()QList::removeAt()方法的内容(另外,如果删除非常常见且列表中有很多项目,那么您可能需要重新考虑这种方法,因为从大阵列中移除速度很慢)。您需要注意,某些Qt代码不会删除该项目,而您无法将其从列表中删除。

如果列表中有项目,将他们的孩子放在列表中,事情会变得更复杂。如果您只删除一个项目,它将删除它的子项,因此如果您的列表中有指向这些项目的指针,那么您的列表将最终指向这些项目的悬空指针。所以,你需要非常仔细地删除。我能想到至少有3种不同的方法(在你自己的代码中递归删除,从项目析构函数中删除列表,使用事件过滤器来捕获项目删除),所以我可以扩展答案,如果这种情况可以发生在您的代码中。

最后注意事项:删除整个场景后,它将删除其所有子项。您需要做的只是确保列表中已删除项目的指针不会被使用,例如只需清除列表即可。