Hi SGM3,
Other aspects of class design are the relationships, "Is a", "Has a", and "Uses a".
"Has a" means that there is another class object (or a collection (list or vector etc) of them, ) inside the class. Example a circle
has a CentrePoint which is of type 2DPoint. A bank has a collection of accounts.
"Uses a" normally means that a class function or constructor takes an argument which is an object of another class. A circle might use an angle to calc an arc length.
Sometimes you can have 2 or 3 relationships. A circle can be defined by 3 points, so it uses these, and it has a centre point as well.
"Is a" implies inheritance - An orange "is" citrus which "is" Fruit, which "is" Human Food. This would be coded like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class CHumanFood {
protected:
double Weight = 0.0;
double EnergyValue = 0.0;
double FatContent = 0.0;
double Carbs = 0.0;
};
class CFruit public CHumanFood {
protected:
string VarietyName ="";
};
class CCitrus public CFruit {
protected:
double VitaminC = 0.0; //Not much imagination here - other things specific to citrus go here as well
};
class COrange public CCitrus {
protected:
//No imagination at all here - put things specific to Oranges here
public:
setValues function
};
|
protected: is just like private but all the derived classes member functions have access as well.
Now all these member variables are inherited, so if you create a MyOrange object, you can set all the values using your setValues function. E.g you can set the Weight variable for the MyOrange object.
The idea is to look at each class, and decide what variables it will have. Then look for ones that are common and put them as high up in the inheritance tree as possible. The same for functions - this means that you should only write the function once.
The example above can be expanded to include Vegetables and Meat say with similar classes for them.
Another example, going back to geometry, is the circle and the arc.
A circle has a centre point and a radius. An arc has centre point, radius, start angle, end angle say (there are multiple ways to define arcs). So the common things are centre point and radius - these are already in circle, so circle is the base class and arc is the derived class. Arc does not have centre & radius in it because they are inherited. The more general things are the base classes and the more specialised things are derived classes.
So that brings me to constructors & overloading functions.
Here is a simple example of overloaded functions:
In C, we have the following functions:
abs (int)
fabs (float or double)
labs (long)
So we have 3 functions that do the same thing - return the absolute value.
In C++, we have function overloading, so we can do this:
abs(int);
abs(float);
abs(double);
abs(long);
When we call the abs function, the compiler knows which one to use by the type of the arguments. This is a form of abstraction, because we can just use the abs function and not worry about what we send it.
As I understand it, the purpose of a constructor is to initialise member variables. If you want to calculate things, then this should be done in a member function. Constructors can be overloaded too, so you can initialise certain variables, then call a function that does a calculation for that combination of information.
So with an arc there are all these different ways to calculate them: 3 pts on arc, 2 pts and radius, 2 pts and centre pt, plus others. Say our arc is to be stored as above with centre point, radius, start angle, end angle. Instead of writing functions with different names to calc the arc, we can write several overloaded constructors, each one will take it's unique combination of types of arguments, and call a function that does that particular calculation. These function would be overloaded as well (say we call them CalcArc), they would take the same args as the constructors. It would be tempting to just to write the constructors, but the purpose of these is to initialise only.
The arguments do have to be unique combinations of types / numbers of args, otherwise the compiler is not going to know which one to call. So in the cases of 3 pts on arc, and 2 pts and centre pt, there is confusion because they both have 3 args which are all of type 2DPoint. To get around this, derive CentrePt and ArcPt from 2DPoint, so now you have 2 types, which solves that problem. You might have derive other point types to solve all the different combinations.
I hope this will help you to sort out the design of your classes. Remember the difference between Is, Uses,and Has. Don't be confused by Is, and Has a collection of.