C ++,Boost:如何在地图容器中存储抽象类型的对象

时间:2012-05-24 14:54:02

标签: c++ boost polymorphism containers smart-pointers

我正在尝试使用地图容器来保存Shapes并将这些形状与ID号匹配。

到目前为止,我一直使用STL容器来保存和管理我的对象。所以我会使用这些类型的容器:

std::map<int, Square> squares;
std::map<int, Triangle> triangles;
std::map<int, Circle> circles;

但是我希望有一个地图来保存“Shapes”,这是一个Square,Triangle和Circle的抽象基类。所以要实现这一点,我仍然会将可实现的派生类对象存储在自己的地图中,然后再生成另一个地图:

std::map<int, Shape*> shapes;

存储指向存储在其他地图中的对象的指针。

这看起来非常混乱,我宁愿将所有对象存储在一个拥有并内存管理所包含对象的多态地图中。

在阅读了一些关于Boost的ptr_map之后,我预计这是解决方案。但似乎基类需要在尝试使用时实现:

boost::ptr_map<int,Shape> shapes;

我收到错误:“错误:无法分配抽象类型'Shape'的对象”

我必须使基类可以实现吗?如果有这样的话,那我就更应该这样做了。

关于如何执行此操作的下一个最佳猜测是使用容器,例如:

std::map<int, boost::shared_ptr<Shape> > shapes;

这似乎是一个直截了当的目标,但由于我遇到这样的困难,我怀疑我正在尝试做一些我不应该做的事情。因此,非常感谢任何有关我可能出错的建议。

感谢。

2 个答案:

答案 0 :(得分:2)

ptr_map<int, Shape>似乎是要走的路,甚至可以使用抽象基类型(参见示例here)。我猜你得到的错误来自于使用operator[]。实际上,就像在std::map中一样,operator[]如果密钥不在地图中,则返回默认构造的值。在这种情况下,它不能构造值,因为Shape是抽象的,因此编译器错误。

因此,您可以使用ptr_map,但不能使用索引运算符。插入时,使用insert,在查找密钥时,请使用find

答案 1 :(得分:1)

您的基类不需要实现。请参阅此处的示例:http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html#associative-containers 那里的动物确实有抽象的功能!实际上,这是ptr容器的主要用途之一。您的错误可能是在其他地方引起的,您需要发布更多代码。

此外:

  

这看起来非常混乱,我宁愿将所有对象存储在一个拥有并内存管理所包含对象的多态地图中。

我认为不是。从不“丢失”实际对象的类型实际上是有益的,以防您以后需要它。例如,如果你想为所有三角形做一些事情,而不是所有其他形状,这将派上用场。

缺点当然是您需要保持所有地图同步,但这很容易解决:将这4个地图(最好是没有其他数据成员!)粘贴到类的私有部分并实现3不同类型的重载,并始终将它们插入到强类型的“拥有”映射中,并插入到具有多态指针的映射中。我很容易让它们在小类接口后面保持同步。只是不要尝试将其作为更大的东西的非结构化部分,否则代码将开始变得混乱。