If you want your Square
be a Rectangle
, it must publicly inherit it. However, this means that any public methods that work with Rectangle
must be appropriately specialized for Square
. In this context
void makeBigger(Rectangle& r)
It should not be a standalone function, but a virtual Rectangle
member that is redefined in Square
(by providing its own) or hidden (via using makeBigger
in the private
section).
Regarding the question that some of the things you can do with a Rectangle
cannot be done with Square
. This is a common design dilemma, and C ++ is not design. If someone has a link (or pointer) to a Rectangle
, which is actually a Square
, and you want to perform an operation that does not make sense for Square
, then you should handle it. There are several options:
1 use public inheritance and throw a Square
exception if the operation is running, which is impossible for Square
struct Rectangle { double width,height; virtual void re_scale(double factor) { width*=factor; height*=factor; } virtual void change_width(double new_width)
This is really inconvenient and not suitable if change_width()
or change_height()
are integral parts of the interface. In this case, consider the following.
2 you can have one class Rectangle
(which may turn out to be square) and, optionally, a separate class Square
that can be converted ( static_cast<Rectangle>(square)
) to Rectangle
and therefore act like a rectangle, but you should not change how a Rectangle
struct Rectangle { double width,height; bool is_square() const { return width==height; } Rectangle(double w, double h) : width(w), height(h) {} };
This option is the right choice if you allow changes to the Rectangle
that can turn it into Square
. In other words, if your Square
not a Rectangle
, as it is implemented in your code (with independently adjustable width and height). However, since Square
can be statically added to a Rectangle
, any function that takes a Rectangle
argument can also be called using Square
.