4 1 1Overloading Operators Overloading operators allows you to apply existing operators to objects of class type.. Arithmetic operators, comparisons, the subscript operator, and the shif
Trang 1S O L U T I O N S 409
inline void go_on()
{
cout << "\n\nGo on with return! ";
cin.sync(); cin.clear(); // No previous input
while( cin.get() != '\n')
;
}
int menu(); // Enter a command
char askForSave(); // Prompt user to save
char header[] =
"\n\n * * * * * Telephone List * * * * *\n\n";
TelList myFriends; // A telephone list
int main()
{
int action = 0; // Command
string name; // Read a name
while( action != 'Q')
{
action = menu();
cls(); cout << header << endl;
switch( action)
{
//
-// case 'S': case 'F': case 'A': case 'D':
// unchanged (refer to the solutions of chapter 16)
//
-case 'O': // To open a file
if(myFriends.isDirty() && askForSave() == 'y')
myFriends.save();
if( myFriends.load())
cout << "Telephone list read from file "
<< myFriends.getFilename() <<"!"
<< endl;
else
cerr << "Telephone list not read!"
<< endl;
go_on();
break;
case 'U': // Save as
if( myFriends.saveAs())
cout << "Telephone list has been saved in file: "
<< myFriends.getFilename() << " !" <<endl;
else
cerr << "Telephone list not saved!" << endl;
go_on();
break;
Trang 2410 C H A P T E R 1 8 F U N D A M E N T A L S O F F I L E I N P U T A N D O U T P U T
case 'W': // Save if( myFriends.save())
cout << "Telephone list has been saved in "
<< "the file "
<< myFriends.getFilename() << endl;
else cerr << "Telephone list not saved!"
<< endl;
go_on();
break;
case 'Q': // Quit if( myFriends.isDirty() && askForSave() == 'Y') myFriends.save();
cls();
break;
} } // End of while return 0;
}
int menu() {
static char menuStr[] = //
"\n -"
"\n O = Open a file"
"\n W = Save "
"\n U = Save as "
"\n -"
"\n Q = Quit the program"
"\n\n Your choice: ";
// -// everything else unchanged (cf solutions in Chapter 16) // -return choice;
}
char askForSave() {
char c;
cout << "Do you want to save the phone list(y/n)? "; do
{ cin.get(c);
c = toupper(c);
}while( c != 'Y' && c != 'N');
return c;
}
Trang 34 1 1
Overloading Operators
Overloading operators allows you to apply existing operators to objects
of class type For example, you can stipulate the effect of the + operator for the objects of a particular class
This chapter describes various uses of overloaded operators
Arithmetic operators, comparisons, the subscript operator, and the shift operators for input and output are overloaded to illustrate the
appropriate techniques
The concept of friend functions, which is introduced in this context, is particularly important for overloading operators
Trang 4412 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 assignment operator =, the address operator &, and the comma operator, have a predefined meaning for each built-in type This meaning can be changed for classes by a definition of your own
■ GENERALS
Overloadable operators
䊐 Rules
An operator is always overloaded in conjunction with a class The definition scope of an operator is simply extended—the characteristics of the operator remain unchanged The following rules apply:
■ You cannot create “new operators”—that is, you can only overload existing oper-ators
■ You cannot redefine the operators for fundamental types
■ You cannot change the operands of an operator A binary operator will always be binary and a unary operator will always be unary
■ The precedence and the order of grouping operators of the same precedence remains unchanged
+ - * / %
== != < <= > >=
& | ^ ~ << >>
&& || !
= op=
() []
& * -> , new delete
++
Arithmetic operators
Relational operators
Logical operators Assignment operators ( op is a binary arithmetic
or a binary bitwise operator)
Bitwise operators
Function call, subscript operator Other operators
Operators Meaning
Trang 5G E N E R A L S 413
䊐 Overloading
An operator is said to be overloaded if it is defined for multiple types In other words, overloading an operator means making the operator significant for a new type
Most operators are already overloaded for fundamental types In the case of the expression:
Example: a / b
the operand type determines the machine code created by the compiler for the division operator If both operands are integral types, an integral division is performed; in all other cases floating-point division occurs Thus, different actions are performed depend-ing on the operand types involved
䊐 Operators for Classes
In addition to defining methods, C++ offers the interesting possibility of defining the functionality of a class by means of operators Thus, you can overload the + operator instead of, or in addition to, using the add()method For the objects xandyin this class:
x + y is equivalent to x.add(y)
Using the overloaded operators of a class expressions of this type can be as easily defined
as for fundamental types Expressions using operators are often more intuitive, and thus easier to understand than expressions containing function calls
Many operators belonging to the C++ standard library classes are already overloaded This applies to the stringclass, with which you are already familiar
Example: string str1("Hello "), str2("Eve");
str1 += str2; // Operator +=
if( str2 < "Alexa") // Operator <
cout << str1; // Operator <<
str2[2] = 'i'; // Operators [] and =
The tables on the opposite page show those operators that can be overloaded Some operators cannot be overloaded, such as the cast operators, the sizeof operator, and the following four operators:
:: * member access and scope resolution operators
?: conditional operator
These operators either have a fixed significance in the classes for which they are defined,
or overloading the operator makes no sense
Trang 6414 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
// DayTime.h // The class DayTime containing operators < and ++ //
-#ifndef _DAYTIME_
#define _DAYTIME_
class DayTime {
private:
short hour, minute, second;
bool overflow;
public:
DayTime( int h = 0, int m = 0, int s = 0);
bool setTime(int hour, int minute, int second = 0); 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); } bool operator<( const DayTime& t) const // compare { // *this and t return asSeconds() < t.asSeconds();
} DayTime& operator++() // Increment seconds {
++second; // and handle overflow return *this;
} void print() const;
};
#endif // _DAYTIME_
#include "DayTime.h"
DayTime depart1( 11, 11, 11), depart2(12,0,0);
if( depart1 < depart2 ) cout << "\nThe 1st plane takes off earlier!" << endl;
■ OPERATOR FUNCTIONS (1)
Operators < and ++ for class DayTime
Calling the Operator <
Trang 7O P E R A T O R F U N C T I O N S ( 1 ) 415
䊐 Naming Operator Functions
To overload an operator, you just define an appropriate operator function The operator
function describes the actions to be performed by the operator The name of an operator function must begin with the operatorkeyword followed by the operator symbol
Example: operator+
This is the name of the operator function for the + operator
An operator function can be defined as a global function or as a class method Gener-ally, operator functions are defined as methods, especially in the case of unary operators However, it can make sense to define an operator function globally This point will be illustrated later
䊐 Operator Functions as Methods
If you define the operator function of a binary operator as a method, the left operand will
always be an object of the class in question The operator function is called for this object The second, right operand is passed as an argument to the method The method
thus has a single parameter.
Example: bool operator<( const DayTime& t) const;
In this case the lesser than operator is overloaded to compare two DayTimeobjects It replaces the method isLess(), which was formerly defined for this class
The prefix operator ++has been overloaded in the example on the opposite page to illustrate overloading unary operators The corresponding operator function in this class has no parameters The function is called if the object a in the expression ++a is an object of class DayTime
䊐 Calling an Operator Function
The example opposite compares two times of day:
Example: depart1 < depart2
The compiler will attempt to locate an applicable operator function for this expression and then call the function The expression is thus equivalent to
depart1.operator<( depart2)
Although somewhat uncommon, you can call an operator function explicitly The previ-ous function call is therefore technically correct
Programs that use operators are easier to encode and read However, you should be aware of the fact that an operator function should perform a similar operation to the cor-responding operator for the fundamental type Any other use can lead to confusion
Trang 8416 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
// Euro1.h : The class Euro containing arithmetic operators //
-#ifndef _EURO_H_
#define _EURO_H_
#include <sstream> // The class stringstream
#include <iomanip>
using namespace std;
class Euro
{ private:
long data; // Euros * 100 + Cents public:
Euro( int euro = 0, int cents = 0)
{ data = 100L * (long)euro + cents;
}
Euro( double x)
{
x *= 100.0; // Rounding, data = (long)(x>=0.0 ? x+0.5 : x-0.5); //ex 9.7 -> 10 }
long getWholePart() const { return data/100; } int getCents() const { return (int)(data%100); } double asDouble() const { return (double)data/100.0; } string asString() const; // Euro as string.
void print( ostream& os) const // Output to stream os { os << asString() << " Euro" << endl; }
// Operator functions Euro operator-() const // Negation (unary minus)) {
Euro temp;
temp.data = -data;
return temp;
} Euro operator+ ( const Euro& e2) const // Addition {
Euro temp;
temp.data = data + e2.data;
return temp;
} Euro operator-( const Euro& e2) const // Subtraction { /* Analog just as operator + */ }
Euro& operator+=( const Euro& e2) // Add Euros {
data += e2.data;
return *this;
} Euro& operator-=( const Euro& e2); // Subtract euros { /* Just as operator += */ }
};
// Continued on the next double page.
■ OPERATOR FUNCTIONS(2)
Class Euro
Trang 9O P E R A T O R F U N C T I O N S ( 2 ) 417
䊐 Notes on the Sample Class Euro
The opposite page shows the Euroclass, which represents the new European currency The member datastores a given amount of euros as an integer in the format:
(integer part)*100 + Cents
Thusdata/100returns the number of euros and data%100the number of cents This technique allows for easy implementation of the arithmetic operations needed for the
Euroclass
In addition to a constructor that is passed whole euros and cents as arguments, there is
a constructor that can process a doublevalue of euros and a standard copy constructor
Example: Euro e1(9,50), e2(20.07), e3(-e1);
䊐 Negation, Addition, and Subtraction
The unary operator -does not change its operand In the previous example, e3is thus assigned a value of -9,50 euro, but e1remains unchanged The operator function is thus a constmethod that creates and returns a temporary object
The binary operators +and-do not change their operands either Thus, the operator functions also create temporary objects and return them with the correct values
Example: Euro sum = e1 + e2;
The expression e1 + e2results in e1.operator+(e2) The return value is used to initialize the new object, sum
䊐 The += and -= Operators
Although the operators +and-were overloaded for the Euroclass, this does not auto-matically mean that the operators +=and-=are overloaded Both are distinct operators that require separate definitions Of course, you should overload the operators to ensure that the statements
Example: sum += e3; and sum = sum + e3;
produce the same results
The binary operators +=and-=change the current object, that is, the left operand A temporary object is not required! The expression sum += e3represents the current object after modification Thus, the operator function returns a reference to *this
Trang 10418 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
// Continues file Euro1.h // -inline string Euro::asString() const // Euro as string {
stringstream strStream; // Stream for conversion long temp = data;
if( temp < 0) { strStream << '-'; temp = -temp; } strStream << temp/100 << ','
<< setfill('0') << setw(2) << temp%100; return strStream.str();
}
#endif // _EURO_H_
// Euro1_t.cpp // Tests the operators of class Euro
//
-#include "Euro1.h" // Definition of the class
#include <iostream>
using namespace std;
int main() {
cout << "* * * Testing the class Euro * * *\n" << endl; Euro wholesale( 20,50), retail;
retail = wholesale; // Standard assignment retail += 9.49; // += (Euro)9.49
cout << "Wholesale price: "; wholesale.print(cout); cout << "Retail price: "; retail.print(cout);
Euro discount( 2.10); // double-constructor retail -= discount;
cout << "\nRetail price including discount: ";
retail.print(cout);
wholesale = 34.10;
cout << "\nNew wholesale price: ";
wholesale.print(cout);
Euro profit( retail - wholesale); // Subtraction and
// copy constructor cout << "\nThe profit: ";
profit.print(cout); // Negative!
return 0;
}
■ USING OVERLOADED OPERATORS File Euro1.h continued
Sample program