Absolute C++ (4th Edition) part 31 docx

10 287 0
Absolute C++ (4th Edition) part 31 docx

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

Thông tin tài liệu

304 Operator Overloading, Friends, and References Display 8.1 Operator Overloading (part 1 of 5) 1 #include <iostream> 2 #include <cstdlib> 3 #include <cmath> 4 using namespace std; 5 //Class for amounts of money in U.S. currency 6 class Money 7 { 8 public: 9 Money( ); 10 Money(double amount); 11 Money(int theDollars, int theCents); 12 Money(int theDollars); 13 double getAmount( ) const; 14 int getDollars( ) const; 15 int getCents( ) const; 16 void input( ); //Reads the dollar sign as well as the amount number. 17 void output( ) const; 18 private: 19 int dollars; //A negative amount is represented as negative dollars and 20 int cents; //negative cents. Negative $4.50 is represented as -4 and -50. 21 int dollarsPart(double amount) const; 22 int centsPart(double amount) const; 23 int round(double number) const; 24 }; 25 const Money operator +(const Money& amount1, const Money& amount2); 26 const Money operator -(const Money& amount1, const Money& amount2); 27 bool operator ==(const Money& amount1, const Money& amount2); 28 const Money operator -(const Money& amount); 29 int main( ) 30 { 31 Money yourAmount, myAmount(10, 9); 32 cout << "Enter an amount of money: "; 33 yourAmount.input( ); 34 cout << "Your amount is "; 35 yourAmount.output( ); 36 cout << endl; 37 cout << "My amount is "; 38 myAmount.output( ); 39 cout << endl; This is a unary operator and is discussed in the subsection OO OO vv vv ee ee rr rr ll ll oo oo aa aa dd dd ii ii nn nn gg gg UU UU nn nn aa aa rr rr yy yy OO OO pp pp ee ee rr rr aa aa tt tt oo oo rr rr ss ss For an explanation of a const on a returned type see the subsection RR RR ee ee tt tt uu uu rr rr nn nn ii ii nn nn gg gg bb bb yy yy const VV VV aa aa ll ll uu uu ee ee . 08_CH08.fm Page 304 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 305 Display 8.1 Operator Overloading (part 2 of 5) 40 if (yourAmount == myAmount) 41 cout << "We have the same amounts.\n"; 42 else 43 cout << "One of us is richer.\n"; 44 Money ourAmount = yourAmount + myAmount; 45 yourAmount.output( ); cout << " + "; myAmount.output( ); 46 cout << " equals "; ourAmount.output( ); cout << endl; 47 Money diffAmount = yourAmount - myAmount; 48 yourAmount.output( ); cout << " - "; myAmount.output( ); 49 cout << " equals "; diffAmount.output( ); cout << endl; 50 return 0; 51 } 52 const Money operator +(const Money& amount1, const Money& amount2) 53 { 54 int allCents1 = amount1.getCents( ) + amount1.getDollars( )*100; 55 int allCents2 = amount2.getCents( ) + amount2.getDollars( )*100; 56 int sumAllCents = allCents1 + allCents2; 57 int absAllCents = abs(sumAllCents); //Money can be negative. 58 int finalDollars = absAllCents/100; 59 int finalCents = absAllCents%100; 60 if (sumAllCents < 0) 61 { 62 finalDollars = -finalDollars; 63 finalCents = -finalCents; 64 } 65 return Money(finalDollars, finalCents); 66 } 67 //Uses cstdlib: 68 const Money operator -(const Money& amount1, const Money& amount2) 69 { 70 int allCents1 = amount1.getCents( ) + amount1.getDollars( )*100; 71 int allCents2 = amount2.getCents( ) + amount2.getDollars( )*100; 72 int diffAllCents = allCents1 - allCents2; 73 int absAllCents = abs(diffAllCents); 74 int finalDollars = absAllCents/100; 75 int finalCents = absAllCents%100; 76 if (diffAllCents < 0) 77 { 78 finalDollars = -finalDollars; Note that we need to use accessor and mutator functions. If the return statements puzzle you, see the tip entitled AA AA CC CC oo oo nn nn ss ss tt tt rr rr uu uu cc cc tt tt oo oo rr rr CC CC aa aa nn nn RR RR ee ee tt tt uu uu rr rr nn nn aa aa nn nn OO OO bb bb jj jj ee ee cc cc tt tt . 08_CH08.fm Page 305 Wednesday, August 13, 2003 1:02 PM 306 Operator Overloading, Friends, and References Display 8.1 Operator Overloading (part 3 of 5) 79 finalCents = -finalCents; 80 } 81 return Money(finalDollars, finalCents); 82 } 83 bool operator ==(const Money& amount1, const Money& amount2) 84 { 85 return ((amount1.getDollars( ) == amount2.getDollars( )) 86 && (amount1.getCents( ) == amount2.getCents( ))); 87 } 88 const Money operator -(const Money& amount) 89 { 90 return Money(-amount.getDollars( ), -amount.getCents( )); 91 } 92 Money::Money( ): dollars(0), cents(0) 93 {/*Body intentionally empty.*/} 94 Money::Money(double amount) 95 : dollars(dollarsPart(amount)), cents(centsPart(amount)) 96 {/*Body intentionally empty*/} 97 Money::Money(int theDollars) 98 : dollars(theDollars), cents(0) 99 {/*Body intentionally empty*/} 100 101 //Uses cstdlib: 102 Money::Money(int theDollars, int theCents) 103 { 104 if ((theDollars < 0 && theCents > 0) || (theDollars > 0 && theCents < 0)) 105 { 106 cout << "Inconsistent money data.\n"; 107 exit(1); 108 } 109 dollars = theDollars; 110 cents = theCents; 111 } 112 double Money::getAmount( ) const 113 { 114 return (dollars + cents*0.01); 115 } 116 int Money::getDollars( ) const If you prefer, you could make these short constructor definitions inline function definitions as discussed in Chapter 7. 08_CH08.fm Page 306 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 307 Display 8.1 Operator Overloading (part 4 of 5) 117 { 118 return dollars; 119 } 120 int Money::getCents( ) const 121 { 122 return cents; 123 } 124 //Uses iostream and cstdlib: 125 void Money::output( ) const 126 { 127 int absDollars = abs(dollars); 128 int absCents = abs(cents); 129 if (dollars < 0 || cents < 0)//accounts for dollars == 0 or cents == 0 130 cout << "$-"; 131 else 132 cout << ’$’; 133 cout << absDollars; 134 135 if (absCents >= 10) 136 cout << ’.’ << absCents; 137 else 138 cout << ’.’ << ’0’ << absCents; 139 } 140 //Uses iostream and cstdlib: 141 void Money::input( ) 142 { 143 char dollarSign; 144 cin >> dollarSign; //hopefully 145 if (dollarSign != ’$’) 146 { 147 cout << "No dollar sign in Money input.\n"; 148 exit(1); 149 } 150 double amountAsDouble; 151 cin >> amountAsDouble; 152 dollars = dollarsPart(amountAsDouble); 153 cents = centsPart(amountAsDouble); 154 } 155 int Money::dollarsPart(double amount) const 156 < The rest of the definition is the same as BankAccount::dollarsPart in Display 7.2. > For a better definition of the input function, see Self-Test Exercise 3 in Chapter 7. 08_CH08.fm Page 307 Wednesday, August 13, 2003 1:02 PM 308 Operator Overloading, Friends, and References Tip If you look at the main function in the demonstration program in Display 8.1, you will see that the overloaded binary operators +, -, and == are used with objects of the class Money in the same way that +, -, and == are used with the predefined types, such as int and double. You can overload most but not all operators. One major restriction on overloading an operator is that at least one operand must be of a class type. So, for example, you can overload the % operator to apply to two objects of type Money or to an object of type Money and a double, but you cannot overload % to combine two doubles. A C ONSTRUCTOR C AN R ETURN AN O BJECT We often think of a constructor as if it were a void function. However, constructors are special functions with special properties, and sometimes it makes more sense to think of them as return- Display 8.1 Operator Overloading (part 5 of 5) 157 int Money::centsPart(double amount) const 158 < The rest of the definition is the same as BankAccount::centsPart in Display 7.2. > 159 int Money::round(double number) const 160 < The rest of the definition is the same as BankAccount::round in Display 7.2. > S AMPLE D IALOGUE Enter an amount of money: $123.45 Your amount is $123.45 My amount is $10.09. One of us is richer. $123.45 + $10.09 equals $133.54 $123.45 - $10.09 equals $113.36 O PERATOR O VERLOADING A (binary) operator, such as +, -, /, %, and so forth, is simply a function that is called using a dif- ferent syntax for listing its arguments. With a binary operator, the arguments are listed before and after the operator; with a function the arguments are listed in parentheses after the function name. An operator definition is written similar to a function definition, except that the operator definition includes the reserved word operator before the operator name. The predefined oper- ators, such as +, -, and so forth, can be overloaded by giving them a new definition for a class type. An example of overloading the +, -, and == operators is given in Display 8.1. 08_CH08.fm Page 308 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 309 Self-Test Exercises ing a value. Notice the return statement in the definition of the overloaded + operator in Display 8.1, which we repeat below: return Money(finalDollars, finalCents); The expression that is returned is an invocation of the constructor for Money. Although we some- times think of a constructor as a void function, a constructor constructs an object and can also be thought of as returning an object of the class. If you feel uncomfortable with this use of the constructor, it may help to know that this return statement is equivalent to the following, more cumbersome and less efficient, code: Money temp; temp = Money(finalDollars, finalCents); return temp; An expression, such as Money(finalDollars, finalCents), is sometimes called an aa aa nn nn oo oo nn nn yy yy mm mm oo oo uu uu ss ss oo oo bb bb jj jj ee ee cc cc tt tt , since it is not named by any variable. However, it is still a full-fledged object. You can even use it as a calling object, as in the following: Money(finalDollars, finalCents).getDollars( ) The previous expression returns the int value of finalDollars. 1. What is the difference between a (binary) operator and a function? 2. Suppose you wish to overload the operator < so that it applies to the type Money defined in Display 8.1. What do you need to add to the definition of Money given in Display 8.1? 3. Is it possible using operator overloading to change the behavior of + on integers? Why or why not? ■ RETURNING BY const VALUE Notice the returned types in the declarations for overloaded operators for the class Money in Display 8.1. For example, the following is the declaration for the overloaded plus operator as it appears in Display 8.1: const Money operator +(const Money& amount1, const Money& amount2); This subsection explains the const at the start of the line. But before we discuss that first const, let’s make sure we understand all the other details about returning a value. So, let’s first consider the case where that const does not appear in either the declaration or anonymous object 08_CH08.fm Page 309 Wednesday, August 13, 2003 1:02 PM 310 Operator Overloading, Friends, and References definition of the overloaded plus operator. Let’s suppose that the declaration reads as follows: Money operator +(const Money& amount1, const Money& amount2); and let’s see what we can do with the value returned. When an object is returned, for example, (m1 + m2), where m1 and m2 are of type Money, the object can be used to invoke a member function, which may or may not change the value of the member variables in the object (m1 + m2). For example, (m1 + m2).output( ); is perfectly legal. In this case, it does not change the object (m1 + m2). However, if we omitted the const before the type returned for the plus operator, then the following would be legal and would change the values of the member variables of the object (m1 + m2): (m1 + m2).input( ); So, objects can be changed, even when they are not associated with any variable. One way to make sense of this is to note that objects have member variables and thus have some kinds of variables that can be changed. Now let’s assume that everything is as shown in Display 8.1; that is, there is a const before the returned type of each operator that returns an object of type Money. For example, below is the declaration for the overloaded plus operator as it appears in Dis- play 8.1: const Money operator +(const Money& amount1, const Money& amount2); The first const on the line is a new use of the const modifier. This is called returning a value as const or returning by const value or returning by constant value. What the const modifier means in this case is that the returned object cannot be changed. For example, consider the following code: Money m1(10.99), m2(23.57); (m1 + m2).output( ); The invocation of output is perfectly legal because it does not change the object (m1 + m2). However, with that const before the returned type, the following will pro- duce a compiler error message: (m1 + m2).input( ); Why would you want to return by const value? It provides a kind of automatic error checking. When you construct (m1 + m2), you do not want to inadvertently change it. At first this protection from changing an object may seem like too much protection, since you can have return by constant value 08_CH08.fm Page 310 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 311 Money m3; m3 = (m1 + m2); and you very well may want to change m3. No problem—the following is perfectly legal: m3 = (m1 + m2); m3.input( ); The values of m3 and (m1 + m2) are two different objects. The assignment operator does not make m3 the same as the object (m1 + m2). Instead, it copies the values of the member variables of (m1 + m2) into the member variables of m3. With objects of a class, the default assignment operator does not make the two objects the same object, it only copies values of member variables from one object to another object. This distinction is subtle but important. It may help you understand the details if you recall that a variable of a class type and an object of a class type are not the same thing. An object is a value of a class type and may be stored in a variable of a class type, but the variable and the object are not the same thing. In the code m3 = (m1 + m2); the variable m3 and its value (m1 + m2) are different things, just as n and 5 are different things in int n = 5; or in int n = (2 + 3); It may take you a while to become comfortable with this notion of return by const value. In the meantime, a good rule of thumb is to always return class types by const value unless you have an explicit reason not to do so. For most simple programs this will have no effect on your program other than to flag some subtle errors. Note that although it is legal, it is pointless to return basic types, such as int, by const value. The const has no effect in the case of basic types. When a function or oper- ator returns a value of one of the basic types, such as int, double, or char, it returns the value, such as 5, 5.5, or ’A’. It does not return a variable or anything like a variable. 1 Unlike a variable, the value cannot be changed—you cannot change 5. Values of a basic type cannot be changed whether there is a const before the returned type or not. On the other hand, values of a class type—that is, objects—can be changed, since they have member variables, and so the const modifier has an effect on the object returned. 1 Unless the value returned is returned by reference, but return by reference is a topic covered later in this chapter. Here we assume the value is not returned by reference. 08_CH08.fm Page 311 Wednesday, August 13, 2003 1:02 PM 312 Operator Overloading, Friends, and References Tip R ETURNING M EMBER V ARIABLES OF A C LASS T YPE When returning a member variable of a class type, in almost all cases it is important to return the member value by const value. To see why, suppose you do not, as in the example outlined in what follows: class Employee { public: Money getSalary( ) { return salary; } . . . private: Money salary; . . . }; In this example, salary is a private member variable that should not be changeable except by using some accessor function of the class Employee. However, this privateness is easily circum- vented as follows: Employee joe; (joe.getSalary( )).input( ); The lucky employee named joe can now enter any salary she wishes! On the other hand, suppose getSalary returns its value by const value, as follows: class Employee { public: const Money getSalary( ) { return salary; } . . . private: Money salary; . . . }; In this case, the following will give a compiler error message. (joe.getSalary( )).input( ); (The declaration for getSalary should ideally be const Money getSalary( ) const { return salary; } but we did not want to confuse the issue with another kind of const.) 08_CH08.fm Page 312 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 313 Self-Test Exercises 4. Suppose you omit the const at the beginning of the declaration and definition of the over- loaded plus operator for the class Money, so that the value is not returned by const value. Is the following legal? Money m1(10.99), m2(23.57), m3(12.34); (m1 + m2) = m3; Is it legal if the definition of the class Money is as shown in Display 8.1, so that the plus operator returns its value by const value? ■ OVERLOADING UNARY OPERATORS In addition to the binary operators, such as + in x + y, C++ has unary operators, such as the operator - when it is used to mean negation. A unary operator is an operator that takes only one operand (one argument). In the statement below, the unary opera- tor - is used to set the value of a variable x equal to the negative of the value of the vari- able y: x = -y; The increment and decrement operators, ++ and , are other examples of unary oper- ators. You can overload unary operators as well as binary operators. For example, we have overloaded the minus operator - for the type Money (Display 8.1) so that it has both a unary and a binary operator version of the subtraction/negation operator For exam- ple, suppose your program contains this class definition and the following code: Money amount1(10), amount2(6), amount3; Then the following sets the value of amount3 to amount1 minus amount2: amount3 = amount1 - amount2; The following will, then, output $4.00 to the screen: amount3.output( ); On the other hand, the following will set amount3 equal to the negative of amount1: amount3 = -amount1; The following will, then, output -$10.00 to the screen: amount3.output( ); unary operator 08_CH08.fm Page 313 Wednesday, August 13, 2003 1:02 PM . dollarsPart(amountAsDouble); 153 cents = centsPart(amountAsDouble); 154 } 155 int Money::dollarsPart(double amount) const 156 < The rest of the definition is the same as BankAccount::dollarsPart. return- Display 8.1 Operator Overloading (part 5 of 5) 157 int Money::centsPart(double amount) const 158 < The rest of the definition is the same as BankAccount::centsPart in Display 7.2. > 159 int. //negative cents. Negative $4.50 is represented as -4 and -50. 21 int dollarsPart(double amount) const; 22 int centsPart(double amount) const; 23 int round(double number) const; 24 }; 25 const

Ngày đăng: 04/07/2014, 05:21

Từ khóa liên quan

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

Tài liệu liên quan