C++ 接口来修改抽象属性

C++ 接口来修改抽象属性,c++,oop,C++,Oop,我想在元素中创建方法来修改元素的形状(即,如果形状是矩形,我必须能够更改长度和宽度,否则我必须能够向多边形形状添加点等) 例如,我不能声明一个setLength方法,因为setLength只是一个意义,如果_shape是一个矩形形状。一个解决方案是在矩形元素、多边形元素、循环元素中对元素进行子类化,但我希望避免这种解决方案。 您是否看到了另一种方法?可能是您可以执行以下操作: class AbstractShape; class RectangularShape : public Abstrac

我想在元素中创建方法来修改元素的形状(即,如果形状是矩形,我必须能够更改长度和宽度,否则我必须能够向多边形形状添加点等)

例如,我不能声明一个setLength方法,因为setLength只是一个意义,如果_shape是一个矩形形状。一个解决方案是在矩形元素、多边形元素、循环元素中对元素进行子类化,但我希望避免这种解决方案。
您是否看到了另一种方法?

可能是您可以执行以下操作:

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

\u形状上调用无意义函数将打印消息或断言。

除了我提到的基本fat接口实现之外,如果您不想出于任何原因污染抽象基类,一种可能的解决方案是在另一个类上使用fat接口并



还请注意,您可能希望使用
std::unique_ptr
,而不是原始指针访问者模式?矩形也应该是多边形,考虑添加一个间接层来变形。polygon@user1482030所以你想要一个胖接口?我认为你需要提供一个
元素的假设用法,这样我们就可以看到你将如何使用它。然后我们可以回答你的问题(没有任何进一步的信息,我会说一个通常被认为是不好的做法的解决方案:在AbstractShape中添加一个虚拟函数,这样你就可以使用dynamic_cast来区分不同的类型)@StoryTeller请详细说明这是一个“好的”如果shape没有正确的动态类型,则设计添加可能毫无意义的方法?@user1482030大多数情况下,您没有太多选择。在这种情况下,你似乎没有太多选择。这就是为什么我建议在另一个类中添加那些无意义的函数,而不是基类,我想这会尽可能地保持基类的“正确”。例如,现在您可以添加一个
getArea()
函数
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
};
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; 
};
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()"};
    }
}