如果你希望你Square
成为一个 Rectangle
,它应该公开继承它。但是,这意味着任何与 a 一起使用的公共方法都Rectangle
必须针对 a 进行适当的专门化Square
。在这种情况下
void makeBigger(Rectangle& r)
不应该是一个独立的函数,而是一个虚拟成员,Rectangle
它的 inSquare
被覆盖(通过提供它自己的)或隐藏(通过 using makeBigger
在private
部分中)。
关于一些你可以做的事情不能对aRectangle
做的问题Square
。这是一个普遍的设计困境,C++ 与设计无关。如果有人对 a 的引用(或指针)Rectangle
实际上是 aSquare
并且想要执行对 a 没有意义的操作Square
,那么您必须处理它。有几种选择:
1 使用公共继承并在Square
尝试操作时抛出异常Square
struct Rectangle {
double width,height;
virtual void re_scale(double factor)
{ width*=factor; height*=factor; }
virtual void change_width(double new_width) // makes no sense for a square
{ width=new_width; }
virtual void change_height(double new_height) // makes no sense for a square
{ height=new_height; }
};
struct Square : Rectangle {
double side;
void re_scale(double factor)
{ side *= factor; } // fine
void change_width(double)
{ throw std::logic_error("cannot change width for Sqaure"); }
virtual void change_height(double)
{ throw std::logic_error("cannot change height for Sqaure"); }
};
change_width()
如果或者change_height()
是界面的组成部分,这确实很尴尬并且不合适。在这种情况下,请考虑以下事项。
2 你可以有一个class Rectangle
(可能碰巧是方形的),也可以有一个单独class Square
的,可以转换为 ( static_cast<Rectangle>(square)
) 为 aRectangle
并因此充当矩形,但不能像 a 那样修改Rectangle
struct Rectangle {
double width,height;
bool is_square() const
{ return width==height; }
Rectangle(double w, double h) : width(w), height(h) {}
};
// if you still want a separate class, you can have it but it's not a Rectangle
// though it can be made convertible to one
struct Square {
double size;
Square(Rectangle r) : size(r.width) // you may not want this throwing constructor
{ assert(r.is_square()); }
operator Rectangle() const // conversion to Rectangle
{ return Rectangle(size,size); }
};
如果您允许更改Rectangle
可以将其变为Square
. 换句话说,如果您Square
不是 代码中实现的 ,Rectangle
(具有可独立修改的宽度和高度)。但是,由于可以静态转换为 a ,因此也可以使用 a 调用任何带参数的函数。Square
Rectangle
Rectangle
Square