2016-08-23 107 views
1

假設一個Domain存儲一個指向Shape的指針。確切的形狀(TriangleRectangle)在編譯時並不知道,並且在讀取輸入後會清楚。在運行時,我可能需要訪問派生結構的變量,但這是不可能的,因爲指針指向基礎結構。我發現另一種解決方案是「開啓型」,但如答案here中指出的那樣,它是不鼓勵的。他還說多態的好習慣

當你使用多態性時,你不需要關心基類引用/指針背後的內容。

那麼在這種情況下,我很在乎,所以它聽起來像我不應該使用多態。我想下面我做的是一個糟糕的設計,但那麼解決這個問題的好設計是什麼?

struct Shape 
{ 
    int common_variable; 
}; 

struct Triangle: Shape 
{ 
    int triangle_specific_variable; 
}; 

struct Rectangle: Shape 
{ 
    int rectangle_specific_variable; 
}; 

struct Domain 
{ 
    Shape* shape; 
}; 

int main() 
{ 
    Domain domain; 
    //domain.shape = new Triangle(); // depends on input. 
    //domain.shape = new Rectangle(); // depends on input. 

    return 0; 
} 
+0

我不太明白你的問題或你的榜樣。看起來這裏有一個多態的方法可能是有用的,但是我不太瞭解你想要做什麼來幫助。 – callyalater

+0

@callyalater:我需要訪問派生結構特定的變量,但我不能因爲指針指向基礎結構。 – Shibli

+0

如果你想通過'Base'指針訪問'Derived'結構的成員,你可以使用'dynamic_cast',但是你需要創建'Base'類的多態類,例如虛擬的'virtual void f(){ }'功能。 – PcAF

回答

6

你的問題清楚地表明需要多態,只要你想用三角形,rechtangles等工作,你知道,所有這些都是形狀。

爲什麼不建議使用交換機訪問特定數據?

因爲這與多態設計完全相反。而不是使用形狀,繪製它們,計算面積等......您總是需要知道形狀的類型並編寫特定的行爲。想象一下,你已經完成了你的代碼,然後你發現你也想要正方形和圓圈:維護這個是多麼的噩夢。

如何解決這個問題?

您必須從具體類中抽象出來,並定義可以在常規形狀上執行的常規操作。然後將這些操作定義爲虛函數,並在您的代碼中使用Domain,只需調用虛函數即可。

爲了進一步豐裕化,您可以使用從流中返回形狀的工廠方法,而不是從類中創建對象。

例子:

class Shape 
{ 
public: 
    virtual void scale(double scale_factor)=0; 
    virtual void rotate(double angle)=0; 
    virtual void draw(window w)=0; 
    virtual Shape* clone()=0; 
    virtual ~Shape() {} 
}; 

class Triangle: public Shape 
{ 
    Point A, B, C; 
public: 
    Triangle (Point a,Point b, Point c) : A(a), B(b), C(c) { } 
    void scale(double scale_factor) override; 
    void rotate(double angle) override; 
    void draw(window w) override; 
    Shape* clone() { return new Triangle(*this); }  
}; 

... 

int main() 
{ 
    Domain domain, domain2; 
    Window wnd = CreateWindow(...); // depends on your GUI library 
    Point a,b,c; 
    cin >> a >> b >> c; 
    domain.shape = new Triangle(a,b,c); 

    // Once the object is constructed no need to know the details of the shape here 
    domain.shape->rotate(45); 
    domain2.shape = domain.shape->clone(); 
    domain.shape->draw(wnd); 
    ... 
    return 0; 
} 

注意,與智能指針工作會比原始指針更安全;

0

首先。當具體對象具有完全相同的接口時,多形性幾乎總是隻有正確的工具。其次,很少有這種情況,有時多態性比變體更適合。

在這種情況下,我們將行爲推遲到實現中,而不是試圖從對象外部推演出來。要做到這一點

一種方法是「訪客模式」:

struct triangly_thing { int i; }; 
struct rectangly_thing { int i; }; 

struct shape_visitor 
{ 
    virtual void operator()(triangly_thing thing) const 
    { 
     // do triangly things 
    } 

    virtual void operator()(rectangly_thing thing) const 
    { 
     // do rectangly things 
    } 
}; 

struct Shape 
{ 
    int common_variable; 

    virtual void visit(shape_visitor const& visitor) 
    { 

    } 
}; 


struct Triangle: Shape 
{ 
    triangly_thing my_triangly_thing; 

    void visit(shape_visitor const& visitor) override 
    { 
     visitor(my_triangly_thing); 
    } 
}; 

struct Rectangle: Shape 
{ 
    rectangly_thing my_rectangly_thing; 

    void visit(shape_visitor const& visitor) override 
    { 
     visitor(my_rectangly_thing); 
    } 
}; 

struct Domain 
{ 
    Shape* shape; 
}; 

int main() 
{ 
    Domain domain; 

    struct my_shape_visitor_type : shape_visitor 
    { 
     // customise overrides in here 
    } my_shape_visitor; 

    domain.shape->visit(my_shape_visitor); 

    return 0; 
}