Object Oriented Programming: Lecture Notes 05
Author: A. El-Gadi/Faculty of Computer Engineering/Tripoli University
If not overridden, the default constructor would simply allocate memory when the class is instantiated i.e. an object is created. A class can have multiple constructors. To understand, how is this possible we need to understand the idea of function overloading.
If not overridden, the default constructor would simply allocate memory when the class is instantiated i.e. an object is created. A class can have multiple constructors. To understand, how is this possible we need to understand the idea of function overloading.
Function overloading:
Function overloading is the ability to have more than one version of the function that differ only in their passing parameters, but have identical names and return types. Take the following example:
void func1(int x){cout<<"This is the INT version";}
void func1(double x){cout<<"This is DOUBLE double version";}
int main(){int y1; double y2;
func1(y1);//Output: This is the INT version
func1(y2);//Output: This is the DOUBLE version
return 0;
}
In the code above the appropriate function is called based on the passing parameter's type. The compiler will choose the version that matches or closely matches the type of the passing parameter. Therefore, if we pass a float in the code above, the function that takes double as passing parameter will be called.
void func1(int x){cout<<"This is the INT version";}
void func1(double x){cout<<"This is DOUBLE double version";}
int main(){float y;
func1(y);//Output: This is the DOUBLE version
return 0;
}
It is also possible to have overloaded functions for types of the same 'family' such as floats and doubles. However, this is not advisable because it does not meet the expectations of the programming community, which normally expects types of the same family to be cast to one another, rather than being treated differently. Therefore, the example below compiles and runs but is ill-designed:
void func1(float x){cout<<"This is the FLOAT version";}
void func1(double x){cout<<"This is DOUBLE version";}
int main(){float y1; double y2;
func1(y1);//Output: This is the FLOAT version
func1(y2);//Output: This is the DOUBLE version
return 0;
}
Class member functions can also be overloaded. Take the following TimePeriod class. Assume that minutes are as accurate a time as we desire to have. We also want to have a function to add minutes and a function to display the period of time.
class TimePeriod{private:
int minutes;
public:
TimePeriod(){minutes=0;}
void display(){int h,m; h=minutes/60; m=minutes-h*60;
cout<<h<<':'<<m;}
void addMinutes(int m){minutes+=m;}
int get(){return minutes;}
};
But it is also natural to add time in hours as well. We can include another member function to add time in hours, and our class would end up looking like this:
class TimePeriod{private:
int minutes;
public:
TimePeriod(){minutes=0;}
void display(){int h,m; h=minutes/60; m=minutes-h*60;
cout<<h<<':'<<m;}
void addMinutes(int m){minutes+=m;}
void addHours(int h){minutes+=h;}
int get(){return minutes;}
};
However, a better approach that keeps the user of our class from deciding which function to choose when adding time is to overload functions to do the different tasks addMinutes and addHours do. This requires that we have minutes and hours as differentiated types.
class Minutes{public: int min;};
class Hours{public: int hours;};
class TimePeriod{private:
int minutes;
public:
TimePeriod(){minutes=0;}
void display(){int h,m; h=minutes/60; m=minutes-h*60;
cout<<h<<':'<<m;}
void addTime(Minutes m){minutes=minutes+m.min;}
void addTime(Hours h){minutes=minutes+h.hours*60;}
int get(){return minutes;}
};
int main(){Minutes m1; Hours h1; TimePeriod tp1;
m1.min=30; h1.hours=3;
tp1.addTime(m1);//This will call the first overloaded addTime
tp1.addTime(h1);//This will call the second overloaded addTime
tp1.display();//Output: 3:30
return 0;
}
We can even include a function that accepts both hours and minutes and another one that accepts another period of time.
class Minutes{public: int min;};
class Hours{public: int hours;};
class TimePeriod{private:
int minutes;
public:
TimePeriod(){minutes=0;}
void display(){int h,m; h=minutes/60; m=minutes-h*60;
cout<<h<<':'<<m;}
void addTime(Minutes m){minutes=minutes+m.min;}
void addTime(Hours h){minutes=minutes+h.hours*60;}
void addTime(Hours h, Minutes m){addTime(h); addTime(m);}
void addTime(TimePeriod tp){minutes=minutes+tp.get();}
int get(){return minutes;}
};
int main(){Minutes m1; Hours h1; TimePeriod tp1, tp2;
m1.min=30; h1.hours=3;
tp1.addTime(m1);//This will call the first overloaded addTime
tp1.addTime(h1);//This will call the second overloaded addTime
tp1.display();//Output: 3:30
tp2.addTime(m1);//Adds 30 minutes
tp2.addTime(tp1);//Adds 210 minutes
tp2.addTime(h1,m1);//Adds 210 minutes
cout<<'\n';
tp2.display();//Output: 7:30
return 0;
}
Constructor overloading:
To return to our initial concern -that of having multiple constructors- we will add that constructors too can be overloaded. This allows users of the class to initialize objects with the desired values. A constructor that takes parameters is called parametric constructor as opposed to the default constructor that takes no parameters. The following is the class TimePeriod after adding some parametric constructors. In the function main you can find the syntax for the usage of parametric constructors.
class Minutes{public: int min;};
class Hours{public: int hours;};
class TimePeriod{private:
int minutes;
public:
TimePeriod(){minutes=0;}
TimePeriod(Minutes m){minutes=m.min;}
TimePeriod(Hours h){minutes=h.hours*60;}
TimePeriod(Hours h, Minutes m){minutes=h.hours*60+m.min;}
void display(){int h,m; h=minutes/60; m=minutes-h*60;
cout<<h<<':'<<m;}
void addTime(Minutes m){minutes=minutes+m.min;}
void addTime(Hours h){minutes=minutes+h.hours*60;}
void addTime(Hours h, Minutes m){addTime(h); addTime(m);}
void addTime(TimePeriod tp){minutes=minutes+tp.get();}
int get(){return minutes;}
};
int main(){Minutes m1; Hours h1;
m1.min=40; h1.hours=2;
TimePeriod tp1(m1);//Initialize with Minutes object
TimePeriod tp2(h1);//Initialize with Hours object
TimePeriod tp3(h1,m1);//Initialize with Hours and Minutes
tp1.display();//Output: 0:40
tp2.display();//Output: 2:0
tp3.display();//Output: 2:40
return 0;
}
with constructors is it permitted to use member functions in the implementation of the constructor? or do i have to write the full implementation?
ReplyDeleteYes it is permitted. No need to redo what you have already done.
ReplyDelete