Class design is often not as easy as it looks, as
Prashant Gupta PG said, it depends on the situation. Sometimes deriving classes is not warranted.
There are 3 relationships between classes.
1. "IS A" The derived class "IS A" type of the base class, as in a Ninja "IS A" Enemy. This one implies inheritance.
2. "HAS A" A class "HAS A" an object as a member which is of another class type. A circle object "HAS A" CentrePoint member variable which is of the CPoint2D type.
3. "USES A" A class function takes an object of a class type as an argument. As in:
CLine::CLine(CPoint2D Pt1, CPoint2D Pt2 );
When inheritance is required, one of the main ideas is to "push things up as high as possible ", to take advantage of the inheritance, and avoid duplicate member names in different classes. Sometimes this means creating extra classes, as in this example:
Instead of this:
1 2 3 4 5 6 7 8
|
class CFood {};
class CFruit: public CFood {
private:
m_VarietyName
};
class CVege: public CFood {
private:
m_VarietyName};
|
Putting VarietyName into the CFood class isn't a good solution, so do this:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
class CFood {
protected:
CFood(); //protected constructor
};
class CFruitVeg: public CFood {
protected: //derived classes can still have private access to these
m_VarietyName
CFruitVeg(); //protected constructor, so we can't create an object of this particular type
// can still create objects of derived classes
class CFruit: public CFruitVeg {};
class CVege: public CFruitVeg {};
|
Pushing things up the tree, applies to functions as well. You can use virtual functions to make an
interface. Virtual functions
may be redefined in derived classes, to handle the specialised behaviour. You can have pure virtual functions, which
must be redefined in derived classes.
One of the best things is taking advantage of polymorphism with the idea that a pointer to a derived class is a valid pointer to a base class. So you can have a function that takes a pointer to the base class as an argument, but you call the function with a pointer to a derived class. The right virtual function is called because of the derived class pointer. This means you can have 1 function in the base class, instead of overloaded functions for every derived class. This is a very very handy thing.
An example of the "HAS A " relationship, might be bank accounts. There is a class CAccount, and the CBank class has a
<list>
or
<vector>
(or any other container) of CAccount objects. There is no inheritance here - this is a common trap for new players.
So having explained all that, you can have a go at designing your classes, maybe you can post what you have here, and we can see if we can offer any improvements?
Hope your silly season is going well :D Cheers