2

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

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

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

但我想要一个单独的地图来保存“形状”,这是一个方形、三角形和圆形的抽象基类。所以要实现这一点,我还是会把可实现的派生类对象存储在自己的映射中,然后再有另一个映射:

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

存储指向存储在其他映射中的对象的指针。

不过,这似乎很混乱,我宁愿将所有对象存储在一个拥有并内存管理所包含对象的多态映射中。

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

boost::ptr_map<int,Shape> shapes;

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

我必须使基类可实现吗?这将是一个黑客,所以我宁愿正确地做到这一点,如果有这样的方式。

关于如何做到这一点,我的下一个最佳猜测是使用容器,例如:

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

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

谢谢。

4

2 回答 2

2

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

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

于 2012-05-24T16:02:39.183 回答
1

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

还:

不过,这似乎很混乱,我宁愿将所有对象存储在一个拥有并内存管理所包含对象的多态映射中。

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

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

于 2012-05-24T15:57:48.043 回答