2017-06-21 76 views
0
class AbstractShape; 
class RectangularShape : public AbstractShape 
{ 
    void setWidth(double v); 
    void setLength(double v); 
}; 

class CircleShape : public AbstractShape 
{ 
    void setRadius(double v); 
}; 

class PolygonalShape : public AbstractShape 
{ 
    void addPoint(Point p); 
}; 

class Element 
{ 
    protected: 
    AbstractShape* _shape; //RectangularShape, PolygonalShape or CircleShape 
}; 

我想在元素中創建方法來修改元素的形狀_shape(即如果形狀是矩形的,我必須能夠改變長度和寬度,否則我必須能夠添加一個點到多邊形形狀等)。修改抽象屬性的界面

例如,我不能聲明setLength方法,因爲setLength只是_shape是RectangularShape時的含義。一種解決方案是在RectangularElement,PolygonalElement,CircularElement中對Element進行子類化,但我想避免這種解決方案。 你看到另一種方式嗎?

+1

訪客模式? – StoryTeller

+1

一個矩形也應該是一個多邊形,考慮添加一個間接層來變形多邊形 – Curious

+0

@ user1482030所以你想要一個胖接口? – Curious

回答

0

可能是你可以做類似如下:

class Shape 
{ 
    // .... 
    virtual void setWidth(double v) { /* not implemented, throw error ? */ } 
    virtual void setLength(double v){ /* not implemented, throw error ? */} 
    virtual void setRadius(double v){ /* not implemented, throw error ? */} 
    virtual void addPoint(Point p) { /* not implemented, throw error ? */} 
    //.... 
}; 


class RectangularShape : public Shape 
{ 
    void setWidth(double v) override ; 
    void setLength(double v) override; 
}; 

class CircleShape : public Shape 
{ 
    void setRadius(double v) override ; 
}; 

class PolygonalShape : public Shape 
{ 
    void addPoint(Point p) override; 
}; 

class Element 
{ 
    protected: 
    Shape* _shape; //Any shape 
}; 

調用上_shape意義功能將打印的消息或斷言。

0

除了我提到的,如果你不想污染無論出於何種原因您的抽象基類基本脂肪接口的實現,一個可能的解決方案是使用另一個類脂肪接口和capability queries

class AbstractShape {}; 

class RectangularShape : public AbstractShape 
{ 
public: 
    void setWidth(double v); 
    void setLength(double v); 
}; 

class CircleShape : public AbstractShape 
{ 
public: 
    void setRadius(double v); 
}; 

class PolygonalShape : public AbstractShape 
{ 
public: 
    void addPoint(Point p); 
}; 

class Element { 
public: 
    void setWidth(double); 
    void setLength(double); 
    void setRadius(double); 
    void addPoint(Point); 
protected: 
    std::unique_ptr<AbstractShape> shape; 
}; 

setWidth()例如實現可能看起來像這樣

void Element::setWidth(double val) { 
    if (auto rectangle = dynamic_cast<Rectangle*>(this->shape.get())) { 
     rectangle->setWidth(val); 
    } else { 
     throw std::runtime_error{"This type does not implement setWidth()"}; 
    } 
} 

另外請注意,你可能需要使用一個std::unique_ptr而不是一個原始指針。

+0

因此,如果形狀沒有正確的動態類型,那麼添加可能毫無意義的方法是一種「好」設計? – user1482030

+0

@ user1482030大部分時間你沒有多少選擇。在這種情況下,你似乎沒有多少選擇。這就是爲什麼我建議將這些無意義的函數添加到另一個類中,而不是基類,這樣可以儘可能地保持基類「正確」。所以現在你可以添加一個'getArea()'函數 – Curious