The thing about this is that for every 'Shape child' I have to include the width, height, x, y variables separately. Isn't one of the advance of class hierarchy not having to repeat oneself.
Regarding the bold bit -- no. You need to investigate the use of composition vs inheritance. Composition is a tool to allow for code re-use (not repeating yourself). Inheritance is a tool to allow for polymorphism. If you're looking for code re-use, you should default to composition, and only use inheritance where necessary.
Can every shape derivative be descrived with those 4 variables? Bregma hinted earlier that this probably isn't true -- e.g. polygons have a collection of vertices and edges, circles have a radius, squares have an edge-length...
Also, inheritance has more meaning in OOD than "the derived class gets all the base members" -- e.g. when you inherit from a base, you're declaring that the
LSP is valid for your derived class. This means that Square is a Rectangle, and Rectangle is a Square, are both invalid statements in OOP!
In Math, every square is a rectangle, so you might think,
"square is a rectangle, but with a different Area function", but that's not true in OOP.
Inheritance says that any algorithm that works on the base type, must also work on any derived type (
i.e. the derived types can be substituted into existing algorithms) -- but if we drop a square into the following function, it will fail the assertion, therefore Square is not a Rectangle.
void Test( Rectangle* rect )
{
rect->SetWidth(10);
rect->SetHeight(2);
assert( rect->Area() == 20 );
}
If you're making a polymorphic base class, you shouldn't include any variables that aren't going to be common to all derived classes.
If you do have variables that are common to all derived classes, you probably don't need to be using polymorphism either...