6

现在我正在使用 std::pair 来表示 C++ 中的二维点。但是,我对不得不写作感到恼火

typedef std::pair<double, double> Point;

Point difference = Point(p2.first - p1.first,
                         p2.second - p1.second);

而不是能够重载 operator+ 和 operator-。

所以,我的问题是,要让我的点课,我应该

  • 公开派生自 std::pair 并添加我自己的成员函数?这很好,因为我所有的代码都可以保持不变。我不会做类似的事情,std::pair<double, double>* p = new Point;所以我不必担心虚拟析构函数之类的事情。
  • 滚动我自己的 Point 类,这很烦人,因为我正在复制 std::pair 的功能,但是我“以纯粹的方式做”。
  • 为 std::pair 制作 operator+ 和 operator- 的模板特化,诚然我不记得它们是放在源文件还是头文件中。

我想这是有争议的,我真的很想做#1,但我不知道这是否是一个坏主意,因为我听说从 STL 继承是一个禁忌。

4

8 回答 8

14

您可以滚动自己的 Point 类,但在内部使用 std::pair 来存储数据。这可以防止从 STL 问题继承,但仍然使用 std::pair 的功能。

于 2009-04-30T22:08:24.797 回答
2

比自己滚动更好:获取现有的免费矢量/点库。一项推荐:附在《游戏程序员基本数学》中的一项。您可以使用您找到的任何库作为起点,然后从那里优化/专门化/调整。

于 2009-04-30T22:19:04.833 回答
2

如果您想使用 std::pair 的功能,我会支持创建您自己的 Point 类并使用私有继承或组合。typedef 的问题(我相信您知道)是您编写的任何采用 Point 的函数也可以被表示为 std::pair<double, double> 的任何东西使用,这可能是无效的。

考虑到这一点,存在另一种选择,即仅创建一些免费的构建器功能,例如

Point addPoints(const Point& p1, const Point& p2);
Point diffPoints(const Point& p1, const Point& p2);

(函数名称可能会更好)。

于 2009-04-30T22:25:28.060 回答
1

另一种选择可能是让您拥有 Point 类,并让您的类“拥有”代表点坐标的 std::pair 。

很多时候,“HAS A”(组合)关系比“IS A”(继承)关系更可取。

于 2009-04-30T22:09:38.800 回答
1

我认为“最佳实践”会说推出您自己的 Point 课程。通过这种方式,您可以更轻松地完成 3D 制作。

于 2009-04-30T22:09:41.093 回答
1

私有继承又名实现的继承,是你的朋友。

这在逻辑上遵循:a Point 不是 std::pair,您不想进行从 Point 到 std::pair 的公共向上转换,但您确实想使用 std::pair 的内部结构。

另一种可能性是has-a关系或组合:每个Point都有一个它在内部使用的privbate std::pair。

事实上,组合和私有继承之间没有太大区别,除了在后者中您可以在 Point 成员函数中强制向上转换为 std::pair 。

于 2009-04-30T22:12:16.313 回答
0

滚动您自己的 Point 课程。这将允许您在将来用它做任何事情。具体来说,我以前解决过这类问题,我发现有用的是定义我自己的 Point 结构,并创建一个继承自它的 Point 类。

完全披露:我不太喜欢 STL。

于 2009-04-30T22:14:29.197 回答
0

不要从 std::pair 公开继承,因为 std::pair 有一个 operator< 但你的 Point 不应该有。

于 2012-01-24T12:26:11.260 回答