2017-06-21 71 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