Review
The Time demonstration program relies on concepts introduced in earlies chapters. Please review the following as needed:
The overloaded operator version of the Time example begins with the class version of Time and modifies it to use overloaded operators for input, output, and addition. It still consists of three files, and each file requires some modification to complete the conversion to overloaded operators. Two versions of the example follow: The first version uses two member functions to implement the addition operation. In contrast, the second version uses only a single friend (i.e., non-member) function to complete the addition operation.
friend
functions but operator<< and operator>> are always implemented as "friends"The UML class diagram is converted to a C++ class as follows:
#include <iostream> using namespace std; class Time { private: int hours; int minutes; int seconds; public: Time() : hours(0), minutes(0), seconds(0) {} Time(int h, int m, int s) : hours(h), minutes(m), seconds(s) {} Time(int s); Time operator+(Time t2); Time operator+(int i); friend ostream& operator<<(ostream& out, Time& t); friend istream& operator>>(istream& in, Time& t); };
Time + Time
Time + int
int + Time
is not supported by this version of the classoperator<<(ostream& out, Time& t)
operator>>(istream& in, Time& t)
#include "Time.h" #include <iostream> #include <iomanip> using namespace std; Time::Time(int s) { hours = s / 3600; s %= 3600; // s = s % 3600; minutes = s / 60; seconds = s % 60; } Time Time::operator+(Time t2) { int i1 = hours * 3600 + minutes * 60 + seconds; int i2 = t2.hours * 3600 + t2.minutes * 60 + t2.seconds; return Time(i1 + i2); } ostream& operator<<(ostream& out, Time& t) { out.fill('0'); out << t.hours << ":" << setw(2) << t.minutes << ":" << setw(2) << t.seconds; out.fill(' '); return out; } istream& operator>>(istream& in, Time& t) { cout << "Please enter the hours: "; cin >> t.hours; cout << "Please enter the minutes: "; cin >> t.minutes; cout << "Please enter the seconds: "; cin >> t.seconds; return in; }
The read function introduced in chapter 5 and modified for chapter 6 could only read from the console. The read function did not have a parameter representing the source from which the function would read the data. Instead, the function hard-coded cout
as the data source. So including the prompts in the read function itself was appropriate. The operator<< presented in Figure 4 retained the prompts to minimize the changes occurring to the function between chapters.
However, operator<< does include a parameter (the first one) denoting the data source. We can write a program that uses the operator interactively by asking an end-user to input data. However, we can also write a program that runs unattended, reading input from a file. In that case, there is no one to read and respond to the prompt, and the prompt can slow the program. I recommend moving the prompts to the application code (the client that uses the Time class) and adapting them as necessary. The following version of operator>> and in the driver appearing below illustrate this approach.
istream& operator>>(istream& in, Time& t) { in >> t.hours; in >> t.minutes; in >> t.seconds; return in; }
A simple driver program stands in for a Time client and demonstrates calls to the Time functions.
#include <iostream> #include "Time.h" using namespace std; int main() { Time t; cout << "Enter the hours, minutes, and seconds "; cout << "(press \"Enter\" after each entry):" << endl; cin >> t; cout << t << endl; Time s(1, 30, 4); cout << s << endl; Time u = t + s; cout << u << endl; //cout << t + s << endl; // alternate return 0; }
operator>>(cin, t)
or t.operator+(s)
), there is no reason for doing so - if we wanted to use functional notation, we would continue using function names like read, print, and add. Overloaded operators are called using an operator notation:
t + s
cin >> t
cout << s
The two operator+ functions defined in the example above can support two related, but distinct function calls:
Time + Time
Time + int
Mathematically, int + Time
is also valid, but this function call does not match the argument list of either overloaded operator+ function. Furthermore, it is not possible write a version of operator+ as a member function that allows an int as the first argument (Figure 2). Fortunately, an appropriate operator+ function can be created as a non-member friend
function. Furthermore, in conjunction with a conversion constructor, all three calling sequences may be satisfied with a single operator+ function (Figure 3).
friend
function«
and »
. A stereotype is used in this UML class diagram to denote that operator+ is implemented as a friend
functionfriend
functionsThe changes required to convert the Time class to use a friend
function for operator+ are illustrated in the last two figures:
class Time { private: int hours; int minutes; int seconds; public: Time() : hours(0), minutes(0), seconds(0) {} Time(int h, int m, int s) : hours(h), minutes(m), seconds(s) {} Time(int s); friend Time operator+(Time t1, Time t2); friend ostream& operator<<(ostream& out, Time& t); friend istream& operator>>(istream& in, Time& t); };
Time operator+(Time t1, Time t2) { int i1 = t1.hours * 3600 + t1.minutes * 60 + t1.seconds; int i2 = t2.hours * 3600 + t2.minutes * 60 + t2.seconds; return Time(i1 + i2); }
friend
keyword only appears in the class specification, not the function definition.