The prefix and postfix decrement operators -- are distinguished in the same manner.. // ---#ifndef _DAYTIME_ #define _DAYTIME_ #include #include using namespace std; class DayTime { pr
Trang 1When outputting a Euroclass object, price, on screen, the following output statement causes a compiler error:
Example: cout << price;
coutcan only send objects to standard output if an output function has been defined for
the type in question—and this, of course, is not the case for user-defined classes.
However, the compiler can process the previous statement if it can locate a suitable operator function, operator<<() To allow for the previous statement, you therefore need to define a corresponding function
䊐 Overloading the << Operator
In the previous example, the left operand of <<is the object cout, which belongs to the
ostreamclass Since the standard class ostreamshould not be modified, it is necessary
to define a global operator function with two parameters The right operand is a Euro
class object Thus the following prototype applies for the operator function:
Prototype: ostream& operator<<(ostream& os, const Euro& e);
The return value of the operator function is a reference to ostream This allows for nor-mal concatenation of operators
Example: cout << price << endl;
䊐 Overloading the >> Operator
The>>operator is overloaded for input to allow for the following statements
Example: cout << "Enter the price in Euros: "
cin >> price;
The second statement causes the following call:
operator>>( cin, price);
Ascinis an object of the standard istreamclass, the first parameter of the operator function is declared as a reference to istream The second parameter is again a refer-ence to Euro
The header file Euro.hcontains only the declarations of <<and>> To allow these functions to access the private members of the Euroclass, you can add a friend decla-ration within the class However, this is not necessary for the current example
Trang 2430 C H A P T E R 1 9 O V E R L O A D I N G O P E R A T O R S
The expression obj++represents a copy of objbefore incrementing
The prefix and postfix decrement operators are distinguished in the same manner
✓ NOTE
Optimized error handling for the Fractionclass will be discussed in Chapter
28, “Exception Handling”
✓ NOTE
Addition
Subtraction
Multiplication
Division
a -b
c -d
a*d + b*c b*d
a -b
c -d
a*d - b*c b*d
a -b
c -d
a * c
b * d
a -b
c -d
a * d
b * c
++obj (Prefix)
obj++ (Postfix)
obj.operator++()
obj.operator++(0)
Prefix and postfix increment
To distinguish the postfix increment operator from the prefix increment operator, the postfix operator function has an additional parameter of type int.
For exercise 2: Calculating with fractions
Trang 3Exercise 1
The<and++operators for the sample class DayTimewere overloaded at the beginning of this chapter Now modify the class as follows:
■ Overload the relational operators
< > <= >= == and !=
and the shift operators
>>and<<for input and output
using global operator functions.You can define these inlinein the header file.
■ Then overload both the prefix and postfix versions of the ++and
operators.The operator functions are methods of the class.The oper-ator decrements the time by one second.The time is not decremented after reaching 0:0:0.
■ Write a main function that executes all the overloaded operators and dis-plays their results.
Exercise 2
You are to develop a class that represents fractions and performs typical
arithmetic operations with them.
■ Use a header file called fraction.h to define the Fractionclass with a numerator and a denominator of type long.The constructor has two parameters of type long: the first parameter (numerator) contains the default value 0, and the second parameter (denominator) contains the value 1 Declare operator functions as methods for -(unary),++and
(prefix only),+=,-=,*=, and /=.The operator functions of the binary operators+,-,*,/and the input / output operators <<,>>are to be declared as friendfunctions of the Fractionclass.
■ Implement the constructor for the Fractionclass to obtain a positive value for the denominator at all times If the denominator assumes a value
of 0, issue an error message and terminate the program.Then write the operator functions.The formulae for arithmetic operations are shown opposite.
■ Then write a mainfunction that calls all the operators in the Fraction
class as a test application Output both the operands and the results.
Trang 4432 C H A P T E R 1 9 O V E R L O A D I N G O P E R A T O R S
Exercise 1
//
// Class DayTime with all relational operators, // the operators ++ and (prefix and postfix), // such as the operators << and >> for input/output //
-#ifndef _DAYTIME_
#define _DAYTIME_
#include <iostream>
#include <iomanip>
using namespace std;
class DayTime {
private:
short hour, minute, second;
bool overflow, underflow;
void inc() // private function for ++ {
++second;
if( second >= 60) // handle overflow
second = 0, ++minute;
if( minute >= 60) minute = 0, ++hour;
if( hour >= 24) hour = 0, overflow = true;
} void dec() // private function for {
second;
if( second < 0) // handle underflow
second = 59, minute;
if( minute < 0) minute = 59, hour;
if( hour < 0) hour = 0, underflow = true;
} public:
DayTime( int h = 0, int m = 0, int s = 0) {
overflow = underflow = false;
if( !setTime( h, m, s)) hour = minute = second = 0;
}
Trang 5bool setTime(int hour, int minute, int second = 0)
{
if( hour >= 0 && hour < 24
&& minute >= 0 && minute < 60
&& second >= 0 && second < 60 )
{
this->hour = (short)hour;
this->minute = (short)minute;
this->second = (short)second;
return true;
}
else
return false;
}
int getHour() const { return hour; }
int getMinute() const { return minute; };
int getSecond() const { return second; };
int asSeconds() const // daytime in seconds
{
return (60*60*hour + 60*minute + second);
}
DayTime& operator++() // ++Seconds
{
inc();
return *this;
}
DayTime operator++(int) // Seconds++
{
DayTime temp(*this);
inc();
return temp;
}
DayTime& operator- -() // Seconds
{
dec();
return *this;
}
DayTime operator- -(int) //
Seconds {
DayTime temp(*this);
dec();
return temp;
}
};
// Relational operators
-// t1 < t2
inline bool operator<( const DayTime& t1,
const DayTime& t2) { return t1.asSeconds() < t2.asSeconds(); }
Trang 6434 C H A P T E R 1 9 O V E R L O A D I N G O P E R A T O R S
// t1 <= t2 inline bool operator<=( const DayTime& t1,
const DayTime& t2) { return t1.asSeconds() <= t2.asSeconds(); } // t1 == t2
inline bool operator==( const DayTime& t1,
const DayTime& t2) { return t1.asSeconds() == t2.asSeconds(); } // t1 != t2
inline bool operator!=( const DayTime& t1,
const DayTime& t2) { return !(t1 == t2); }
// t1 > t2 inline bool operator>( const DayTime& t1,
const DayTime& t2) { return (t2 < t1); }
// t1 >= t2 inline bool operator>=(const DayTime& t1,const DayTime& t2) { return !(t1 < t2); }
// Input and Output -ostream& operator<<( ostream& os, const DayTime& t) {
os << setfill('0')
<< setw(2) << t.getHour() << ':'
<< setw(2) << t.getMinute() << ':'
<< setw(2) << t.getSecond() << " Time";
os << setfill(' ');
return os;
} istream& operator>>( istream& is, DayTime& t) {
cout << "Enter daytime in hh:mm:ss format: ";
int hr = 0, min = 0, sec = 0;
char c1 = 0, c2 = 0;
if( !(is >> hr >> c1 >> min >> c2 >> sec)) return is;
if( c1 != ':' || c2 != ':' || ! t.setTime(hr,min,sec)) is.setstate( ios::failbit); // Error!
// => Set fail bit return is;
}
#endif // _DAYTIME_
Trang 7//
// Testing the operators of class DayTime
//
-#include "DayTime.h" // Definition of the class
#include <iostream>
using namespace std;
int main()
{
DayTime cinema( 20,30);
cout << "\nThe movie starts at " << cinema << endl;
DayTime now;
cout << "What time is it now?" << endl;
if( !(cin >> now) )
cerr << "Invalid input!" << endl;
else
cout << "\nThe time is now" << now << endl;
cout << "\nThe movie has ";
if( cinema < now)
cout << "already begun!\n" << endl;
else
cout << "not yet begun!\n" << endl;
cout << "Now it is " << now++ << endl;
cout << "After 2 seconds: " << ++now << endl;
DayTime depart(16,0);
cout << "Let's go at " << depart << endl;
if( depart >= now )
cout << "You can ride with us!" << endl;
else
cout << "We don't have room!" << endl;
return 0;
}
Trang 8436 C H A P T E R 1 9 O V E R L O A D I N G O P E R A T O R S
Exercise 2
//
// A numerical class to represent fractions //
-#ifndef _FRACTION_
#define _FRACTION_
#include <iostream>
#include <cstdlib>
using namespace std;
class Fraction {
private:
long numerator, denominator;
public:
Fraction(long n = 0, long d = 1);
Fraction operator-() const {
return Fraction(-numerator, denominator);
} Fraction& operator+=(const Fraction& a) {
numerator = a.numerator * denominator
+ numerator * a.denominator;
denominator *= a.denominator;
return *this;
} Fraction& operator-=(const Fraction& a) {
*this += (-a);
return *this;
} Fraction& operator++() {
numerator += denominator;
return *this;
} Fraction& operator () {
numerator -= denominator;
return *this;
}
Trang 9friend Fraction operator+(const Fraction&, const Fraction&); friend Fraction operator-(const Fraction&, const Fraction&); friend Fraction operator*(const Fraction&, const Fraction&); friend Fraction operator/(const Fraction&, const Fraction&); friend ostream& operator<< (ostream& os, const Fraction& a); friend istream& operator>> (istream& is, Fraction& a);
};
#endif
//
// Defines methods and friend functions
//
-#include "Fraction.h"
// Constructor:
Fraction::Fraction(long n, long d)
{
if(d == 0)
{ cerr << "\nError: Division by zero!\n";
exit(1);
}
if( n < 0 ) n = -n, d = -d;
numerator = n; denominator = d;
}
Fraction operator+(const Fraction& a, const Fraction& b)
{
Fraction temp;
temp.denominator = a.denominator * b.denominator;
temp.numerator = a.numerator*b.denominator
+ b.numerator * a.denominator;
return temp;
}
Fraction operator-(const Fraction& a, const Fraction& b )
{
Fraction temp = a; temp += (-b);
return temp;
}
Fraction operator*(const Fraction& a, const Fraction& b )
{
Fraction temp;
temp.numerator = a.numerator * b.numerator;
temp.denominator = a.denominator * b.denominator;
return temp;
}
Trang 10438 C H A P T E R 1 9 O V E R L O A D I N G O P E R A T O R S
Fraction operator/(const Fraction& a, const Fraction& b ) {
if( b.numerator == 0) {
cerr << "\nError: Division by zero!\n";
exit(1);
} // To multiply a by the inverse of b:
Fraction temp;
temp.numerator = a.numerator * b.denominator;
temp.denominator = a.denominator * b.numerator; if( temp.denominator < 0 )
temp.numerator = -temp.numerator, temp.denominator = -temp.denominator;
return temp;
} ostream& operator<<(ostream& os, const Fraction& a) {
os << a.numerator << "/" << a.denominator;
return os;
} istream& operator>>(istream& is, Fraction& a) {
cout << "Enter a fraction:\n"
" Numerator: "; is >> a.numerator; cout << " Denominator != 0: "; is >> a.denominator; if( !is) return is;
if( a.denominator == 0) {
cout << "\nError: The denominator is 0\n"
" New denominator != 0: ";
is >> a.denominator;
if( a.denominator == 0) {
cerr << "\nError: Division by zero!\n"; exit(1); }
} if( a.denominator < 0 ) a.numerator = -a.numerator, a.denominator= -a.denominator;
return is;
}