2013-07-11 108 views
4

我使用兩個Point s至限定Line並且也是LineSegment,如:如何區分Line Line和Line?

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) { ... } 

當然,我會得到一個編譯錯誤。

所以,我的問題是:有沒有更好的方法來區分LineLineSegment沒有重新定義LineSegment

+1

定義'AbstractLine'有兩個點,然後子類到'Line'和'LineSegment'? – Amadan

+0

而不是使用'Point'作爲'Line',你可以使用一個漸變值,另一個用於y-截距(假設你是2D的)。 –

+0

如果它們相同,則不要區分它們。只有一個定義,因此只有一個功能。不要重複自己。如果他們的功能稍後出現分歧,那麼Amadan的解決方案是一個好主意。 –

回答

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); 
} 
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(); } 
}; 

(唉......現在,我寫的所有,我可以看到,其實你希望代表團在這裏走另一條路,並減去線段的座標產生以正確的角度線。不管怎樣,這工作,你會得到的地步。這種授權可以是雙向的,而繼承通常是單向的。)


而且,你不應該只是typedef東西因爲裏面的數據成員是相似的。爲什麼不只是將它們都定義爲數組呢?一個類表示一個獨特的概念。

我建議不要使用AbstractLine建議,除非有有意義的方法放在那裏。從界面開始,以最方便的方式填寫內部細節。類不應僅僅因爲它們看起來相同而共享實現,而是因爲實現在概念上做同樣的事情。

因爲數學很棘手,所以應該寫數學類以允許更改內部表示,並且公有繼承有點危險。因爲數學不涉及「演員」和行爲,而是涉及像交換性這樣的屬性的泛型操作,所以OOP通常不太適合。

+0

我覺得使用點來定義一條線很方便,因爲我使用vector * dot product *和* cross product *來進行計算。如果我使用抽象類,這兩個類可以共享許多函數,例如,'get_slope',或者什麼... – abcdabcd987

+0

@ abcdabcd987然後,使用繼承。但是使用'private'或'protected'繼承和'using'聲明來暴露接口,所以用戶不會依賴於你不想永遠保證的內部deatails。 – Potatoswatter

+0

如果您考慮語義,並且除非使用情況另有說明(就像本例中那樣),否則您當然是正確的:將(2D)線定義爲方向和偏移量更有意義。我只是在抽象OOP的基礎上解決了「爲什麼這不起作用」的問題:typedef'd類型不是一種不同的類型,並且不能區分簽名,並且子類化使它們不同而仍然共享功能。 – Amadan