我使用两个Point
来定义Line
和LineSegment
,例如:
class Point { ... };
class Line
{
Point p1, p2;
//...
};
class LineSegment
{
Point p1, p2;
//...
};
LineSegment
与Line
具有相同的定义,因此我首先使用typedef Line LineSegment
而不是定义另一个LineSegment
类。但很快,我发现我无法定义函数distance
来计算点与线或点与线段之间的距离。
class Point { ... };
class Line
{
Point p1, p2;
//...
};
typedef Line LineSegment;
double distance(const Point& a, const Line& b) { ... }
double distance(const Point& a, const LineSegment& b) { ... }
当然我会收到编译错误。
所以,我的问题是:如果没有重新定义Line
,是否有更好的方法可以区分LineSegment
和LineSegment
?
答案 0 :(得分:3)
我按照 @Amadan 的建议行事。创建一个抽象类。
#include <iostream>
struct Point { int x, y; };
struct AbstractLine { Point p1, p2; };
struct Line : AbstractLine { };
struct LineSegment : AbstractLine { };
void distance(const Point& a, const Line& b)
{
std::cout << "void distance(const Point& a, const Line& b)" << std::endl;
}
void distance(const Point& a, const LineSegment& b)
{
std::cout << "void distance(const Point& a, const LineSegment& b)" << std::endl;
}
int main()
{
Point p;
Line a;
LineSegment b;
distance(p, a);
distance(p, b);
}
答案 1 :(得分:2)
线段具有起点和终点,而线可以仅由最靠近原点(或其他某种表示)的点唯一定义。
因此Line表示无效或过多。
编辑:啊哈,我知道我错过了什么!如果使用最接近原点(x,y)的直线上的点,那么斜率为(-x / y),并且可以在(x + y,y-x)处轻松构造直线上的第二个点。因此,Line的实现可以计算使用临时对象将操作委派给LineSegment,而不是从内存中加载其他值。 (临时工应完全住在登记簿中。)
class LineSegment {
std::array< Point, 2 > terminus;
public:
double angle() { return ... }
};
class Line {
Point nearest_origin;
LineSegment toLineSegment() {
return {
nearest_origin,
{ nearest_origin[0] + nearest_origin[1],
nearest_origin[1] - nearest_origin[0] }
};
}
public:
double angle()
{ return toLineSegment().angle(); }
};
(呃......现在我写了所有我能看到的,实际上你想要委托在这里走另一条路,并减去LineSegment的坐标以产生一个正确角度的线。无论如何,这有效,你得到了这种授权可以双向进行,而继承通常是单向的。)
此外,您不应仅仅因为内部的数据成员相似而typedef
。为什么不直接将它们解压缩到数组?一个类代表一个独特的概念。
我建议不要使用AbstractLine建议,除非有有意义的方法放在那里。从界面开始,以最方便的方式填写内部详细信息。类不应仅仅因为它们看起来相同而共享实现,而是因为实现在概念上做同样的事情。
因为数学很棘手,所以应该编写数学类以允许更改内部表示,并且公共继承有点危险。因为数学不涉及“演员”和行动,而是具有交换性等属性的通用操作,所以OOP通常不太合适。