Your base class should not contain any information not available to
any descendant. Also, it appears that your base class should be named "Shape", right?
A shape cannot be turned into another type of shape (can it?) so the name of the shape should also not be modifiable. The
name() method should be
const.
Likewise, computing the area of a shape does not change the shape, so the
area() method should also be
const.
A shape cannot exist by itself. (You cannot have a 'dog', but you can have a 'Beagle' or a 'Corgi'.) Hence, the base class's virtual functions must be
abstract -- which is why they have that
= 0
at the end.
1 2 3 4 5 6
|
class Shape
{
public:
virtual string name() const = 0;
virtual double area() const = 0;
};
|
Descendant classes should provide additional members
specific to that type of thing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
class Square: public Shape
{
private:
double length;
public:
Square( double length = 0 ): length( length ) { } // Constructor
virtual string name() const { return "Square"; } // A square is always a square.
virtual double area() const
{
return length * length;
}
double GetLength() const { return length; }
void SetLength( double x ) { length = x; }
};
|
If you wish your object to have a position in space such that you can compute whether or not a point is inside it, you can also define an upper-left corner.
1 2
|
private:
double x, y, length;
|
Many squares and rectangles define coordinates with both upper-left and lower-right corners. (If you do this, though, you have to guarantee that no setter is allowed to make your square non-square.)
1 2
|
private:
double x0, y0, x1, y1;
|
You can then add a virtual function to your base "Shape" class which each descendant class can provide a meaning for:
1 2 3 4 5
|
class Shape
{
public:
...
virtual bool isPointInShape( double x, double y ) const = 0;
|
Hope this helps.