A Complete Guide to Programming in C++ part 46 ppt

10 330 0
A Complete Guide to Programming in C++ part 46 ppt

Đang tải... (xem toàn văn)

Thông tin tài liệu

OVERLOADING SHIFT-OPERATORS FOR I/O ■ 429 When outputting a Euro class object, price, on screen, the following output statement causes a compiler error: Example: cout << price; cout can 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 ostream class. Since the standard class ostream should 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); As cin is an object of the standard istream class, 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.h contains only the declarations of << and >>. To allow these functions to access the private members of the Euro class, you can add a friend decla- ration within the class. However, this is not necessary for the current example. exercises 430 ■ CHAPTER 19 OVERLOADING OPERATORS The expression obj++ represents a copy of obj before incrementing. The prefix and postfix decrement operators are distinguished in the same manner. ✓ NOTE Optimized error handling for the Fraction class 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 Expression Operator Function Call ++obj (Prefix) obj++ (Postfix) obj.operator++() obj.operator++(0) ■ EXERCISES 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 EXERCISES ■ 431 Exercise 1 The < and ++ operators for the sample class DayTime were 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 inline in 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 Fraction class 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 friend functions of the Fraction class. ■ Implement the constructor for the Fraction class 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 main function that calls all the operators in the Fraction class as a test application. Output both the operands and the results. solutions 432 ■ CHAPTER 19 OVERLOADING OPERATORS ■ SOLUTIONS Exercise 1 // // DayTime.h // 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; } SOLUTIONS ■ 433 bool 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(); } 434 ■ CHAPTER 19 OVERLOADING OPERATORS // 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_ SOLUTIONS ■ 435 // // DayTim_t.cpp // 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; } 436 ■ CHAPTER 19 OVERLOADING OPERATORS Exercise 2 // // Fraction.h // 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; } SOLUTIONS ■ 437 friend 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 // // Fraction.cpp // 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; } 438 ■ CHAPTER 19 OVERLOADING OPERATORS 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; } . -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 +. a) { numerator = a. numerator * denominator + numerator * a. denominator; denominator *= a. denominator; return *this; } Fraction& operator-=(const Fraction& a) { *this += ( -a) ; return *this; } Fraction&. 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

Ngày đăng: 06/07/2014, 17:21

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan