如何区分LineSegment和Line?

时间:2013-07-11 01:10:19

标签: c++ class

我使用两个Point来定义LineLineSegment,例如:

class Point { ... };
class Line
{
  Point p1, p2;
  //...
};
class LineSegment
{
  Point p1, p2;
  //...
};

LineSegmentLine具有相同的定义,因此我首先使用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 ,是否有更好的方法可以区分LineSegmentLineSegment

2 个答案:

答案 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通常不太合适。