Absolute C++ (4th Edition) part 30 pdf

10 1.4K 1
Absolute C++ (4th Edition) part 30 pdf

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

Thông tin tài liệu

Vectors—A Preview of the Standard Template Library 293 Pitfall The vector definition is given in the library vector, which places it in the std namespace. Thus, a file that uses vectors would include the following (or something similar): #include <vector> using namespace std; U SING S QUARE B RACKETS BEYOND THE V ECTOR S IZE If v is a vector and i is greater than or equal to v.size( ), then the element v[i] does not yet exits and needs to be created by using push_back to add elements up to and including position i. If you try to set v[i] for i greater than or equal to v.size( ), as in v[i] = n; then you may or may not get an error message, but your program will undoubtedly misbehave at some point. V ECTORS Vectors are used very much like arrays, but a vector does not have a fixed size. If it needs more capacity to store another element, its capacity is automatically increased. Vectors are defined in the library vector, which places them in the std namespace. Thus, a file that uses vectors would include the following lines: #include <vector> using namespace std; The vector class for a given Base_Type is written vector< Base_Type >. Two sample vector decla- rations are as follows: vector<int> v; //default constructor producing an empty vector. vector<AClass> record(20); //vector constructor uses the //default constructor for AClass to initialize 20 elements. Elements are added to a vector using the member function push_back, as illustrated below: v.push_back(42); Once an element position has received its first element, either with push_back or with a con- structor initialization, that element position can then be accessed using square bracket notation, just like an array element. 07_CH07.fm Page 293 Wednesday, August 13, 2003 12:58 PM 294 Constructors and Other Tools Tip V ECTOR A SSIGNMENT I S W ELL B EHAVED The assignment operator with vectors does an element-by-element assignment to the vector on the left-hand side of the assignment operator (increasing capacity if needed and resetting the size of the vector on the left-hand side of the assignment operator). Thus, provided the assign- ment operator on the base type makes an independent copy of an element of the base type, then the assignment operator on the vector will make an independent copy, not an alias, of the vector on the right-hand side of the assignment operator. Note that for the assignment operator to produce a totally independent copy of the vector on the right-hand side of the assignment operator requires that the assignment operator on the base type make completely independent copies. The assignment operator on a vector is only as good (or bad) as the assignment operator on its base type. ■ EFFICIENCY ISSUES At any point in time a vector has a capacity, which is the number of elements for which it currently has memory allocated. The member function capacity( ) can be used to find out the capacity of a vector. Do not confuse the capacity of a vector with the size of a vector. The size is the number of elements in a vector, whereas the capacity is the number of elements for which there is memory allocated. Typically the capacity is larger than the size, and the capacity is always greater than or equal to the size. Whenever a vector runs out of capacity and needs room for an additional member, the capacity is automatically increased. The exact amount of the increase is implemen- tation dependent, but always allows for more capacity than is immediately needed. A commonly used implementation scheme is for the capacity to double whenever it needs to increase. Because increasing capacity is a complex task, this approach of reallocating capacity in large chunks is more efficient than allocating numerous small chunks. You can completely ignore the capacity of a vector and that will have no effect on what your program does. However, if efficiency is an issue, you may want to manage capacity yourself and not simply accept the default behavior of doubling capacity whenever more is needed. You can use the member function reserve to explicitly increase the capacity of a vector. For example, v.reserve(32); sets the capacity to at least 32 elements, and v.reserve(v.size( ) + 10); sets the capacity to at least 10 more than the number of elements currently in the vec- tor. Note that you can rely on v.reserve to increase the capacity of a vector, but it does not necessarily decrease the capacity of a vector if the argument is smaller than the cur- rent capacity. capacity 07_CH07.fm Page 294 Wednesday, August 13, 2003 12:58 PM Vectors—A Preview of the Standard Template Library 295 Self-Test Exercises You can change the size of a vector using the member function resize. For example, the following resizes a vector to 24 elements: v.resize(24); If the previous size were less than 24, then the new elements are initialized as we described for the constructor with an integer argument. If the previous size were greater than 24, then all but the first 24 elements are lost. The capacity is automatically increased if need be. Using resize and reserve, you can shrink the size and capacity of a vector when there is no longer any need for some elements or some capacity. 9. Is the following program legal? If so, what is the output? #include <iostream> #include <vector> using namespace std; int main( ) { vector<int> v(10); int i; for (i = 0; i < v.size( ); i++) v[i] = i; vector<int> copy; copy = v; v[0] = 42; for (i = 0; i < copy.size( ); i++) cout << copy[i] << " "; cout << endl; return 0; } 10. What is the difference between the size and the capacity of a vector? S IZE AND C APACITY The size of a vector is the number of elements in the vector. The capacity of a vector is the number of elements for which it currently has memory allocated. For a vector v, the size and capacity can be recovered with the member functions v.size( ) and v.capacity( ). 07_CH07.fm Page 295 Wednesday, August 13, 2003 12:58 PM 296 Constructors and Other Tools ■ A constructor is a member function of a class that is called automatically when an object of the class is declared. A constructor must have the same name as the class of which it is a member. ■ A default constructor is a constructor with no parameters. You should always define a default constructor for your classes. ■ A member variable for a class may itself be of a class type. If a class has a class mem- ber variable, then the member variable constructor can be invoked in the initializa- tion section of the outer class constructor. ■ A constant call-by-reference parameter is more efficient than a call-by-value parame- ter for class type parameters. ■ Making very short function definitions inline can improve the efficiency of your code. ■ Static member variables are variables that are shared by all objects of a class. ■ Vector classes have objects that behave very much like arrays whose capacity to hold elements will automatically increase if more capacity is needed. ANSWERS TO SELF-TEST EXERCISES 1. YourClass anObject(42, ’A’); //LEGAL YourClass anotherObject; //LEGAL YourClass yetAnotherObject( ); //PROBLEM anObject = YourClass(99, ’B’); //LEGAL anObject = YourClass( ); //LEGAL anObject = YourClass; //ILLEGAL The statement marked //PROBLEM is not strictly illegal, but it does not mean what you might think it means. If you mean this to be a declaration of an object called yetAnotherObject, then it is wrong. It is a correct declaration for a function called yetAnotherObject that takes zero arguments and that returns a value of type YourClass, but that is not usually the intended meaning. As a practical matter, you can probably consider it illegal. The correct way to declare an object called yetAnotherObject so that it will be initialized with the default constructor is as follows: YourClass yetAnotherObject; 2. A default constructor is a constructor that takes no arguments. Not every class has a default constructor. If you define absolutely no constructors for a class, then a default constructor will be automatically provided. On the other hand, if you define one or more constructors but do not define a default constructor, then your class will have no default constructor. Chapter Summary 07_CH07.fm Page 296 Wednesday, August 13, 2003 12:58 PM Answers to Self-Test Exercises 297 3. The definition is easier to give if you also add a private helping function named BankAc- count::digitToInt , as below, to the class BankAccount. //Uses iostream: void BankAccount::input( ) { int dollars; char point, digit1, digit2; cout << "Enter account balance (include cents even if .00) $"; cin >> dollars; cin >> point >> digit1 >> digit2; accountDollars = dollars; accountCents = digitToInt(digit1)*10 + digitToInt(digit2); if (accountDollars < 0) accountCents = -accountCents; cout << "Enter interest rate (NO percent sign): "; cin >> rate; setRate(rate); } int BankAccount::digitToInt(char digit) { return (static_cast<int>(digit) - static_cast<int>(’0’)); } 4. The member function input changes the value of its calling object, and so the compiler will issue an error message if you add the const modifier. 5. Similarities: Each parameter call method protects the caller’s argument from change. Dif- ferences: If the type is a large structure or class object, a call by value makes a copy of the caller’s argument and thus uses more memory than a call by constant reference. 6. In const int x = 17;, the const keyword promises the compiler that code written by the author will not change the value of x. In the int f( ) const; declaration, the const keyword is a promise to the compiler that code written by the author to implement function f will not change anything in the calling object. In int g(const A& x);, the const keyword is a promise to the compiler that code written by the class author will not change the argument plugged in for x. 7. class DayOfYear { public: DayOfYear(int monthValue, int dayValue); DayOfYear(int monthValue); DayOfYear( ); 07_CH07.fm Page 297 Wednesday, August 13, 2003 12:58 PM 298 Constructors and Other Tools void input( ); void output( ); int getMonthNumber( ) { return month; } int getDay( ) { return day; } private: int month; int day; void testDate( ); }; 8. No, it cannot be a static member function because it requires a calling object for the mem- ber variable name. 9. The program is legal. The output is 0 1 2 3 4 5 6 7 8 9 Note that changing v does not change copy. A true independent copy is made with the assignment. copy = v; 10. The size is the number of elements in a vector, while the capacity is number of elements for which there is memory allocated. Typically the capacity is larger than the size. PROGRAMMING PROJECTS 1. Define a class called Month that is an abstract data type for a month. Your class will have one member variable of type int to represent a month (1 for January, 2 for February, and so forth). Include all the following member functions: a constructor to set the month using the first three letters in the name of the month as three arguments, a constructor to set the month using an integer as an argument (1 for January, 2 for February, and so forth), a default constructor, an input function that reads the month as an integer, an input func- tion that reads the month as the first three letters in the name of the month, an output function that outputs the month as an integer, an output function that outputs the month as the first three letters in the name of the month, and a member function that returns the next month as a value of type Month. Embed your class definition in a test program. 2. Redefine the implementation of the class Month described in Programming Project 1. (or do the definition for the first time, but do the implementation as described here). This time the month is implemented as three member variables of type char that store the first three letters in the name of the month. Embed your definition in a test program. 3. My mother always took a little red counter to the grocery store. The counter was used to keep tally of the amount of money she would have spent so far on that visit to the store if she bought everything in the basket. The counter had a four-digit display, increment but- tons for each digit, and a reset button. An overflow indicator came up red if more money was entered than the $99.99 it would register. (This was a long time ago.) 07_CH07.fm Page 298 Wednesday, August 13, 2003 12:58 PM 1 . 7 2 . 6 Programming Projects 299 Write and implement the member functions of a class Counter that simulates and slightly generalizes the behavior of this grocery store counter. The constructor should create a Counter object that can count up to the constructor’s argument. That is, Counter(9999) should provide a counter that can count up to 9999. A newly constructed counter displays a reading of 0. The member function void reset( ); sets the counter’s number to 0. The member function void incr1( ); increments the units digits by 1, void incr10( ); increments the tens digit by 1, and void incr100( ); and void incr1000( ); increment the next two digits, respectively. Accounting for any carrying when you increment should require no further action than adding an appropriate number to the private data member. A member function bool overflow( ); detects overflow. (Overflow is the result of incrementing the counter’s private data member beyond the maximum entered at counter construction.) Use this class to provide a simulation of my mother’s little red clicker. Even though the display is an integer, in the simulation, the rightmost (lower order) two digits are always thought of as cents and tens of cents, the next digit is dollars, and the fourth digit is tens of dollars. Provide keys for cents, dimes, dollars, and tens of dollars. Unfortunately, no choice of keys seems particularly mnemonic. One choice is to use the keys asdfo: a for cents, followed by a digit 1 to 9; s for dimes, followed by a digit 1 to 9; d for dollars, followed by a digit 1 to 9; and f for tens of dollars, again followed by a digit 1 to 9. Each entry (one of asdf followed by 1 to 9) is followed by pressing the Return key. Any overflow is reported after each operation. Overflow can be requested by pressing the o key. 07_CH07.fm Page 299 Wednesday, August 13, 2003 12:58 PM 7.4 For additional online Programming Projects, click the CodeMate icons below. 8 Operator Overloading, Friends, and References 8.1 BASIC OPERATOR OVERLOADING 302 Overloading Basics 303 Tip: A Constructor Can Return an Object 308 Returning by const Value 309 Tip: Returning Member Variables of a Class Type 312 Overloading Unary Operators 313 Overloading as Member Functions 314 Tip: A Class Has Access to All Its Objects 316 Overloading Function Application ( ) 317 Pitfall: Overloading && , || , and the Comma Operator 317 8.2 FRIEND FUNCTIONS AND AUTOMATIC TYPE CONVERSION 318 Constructors for Automatic Type Conversion 318 Pitfall: Member Operators and Automatic Type Conversion 319 Friend Functions 320 Pitfall: Compilers without Friends 323 Friend Classes 323 8.3 REFERENCES AND MORE OVERLOADED OPERATORS 324 References 325 Pitfall: Returning a Reference to Certain Member Variables 327 Overloading >> and << 327 Tip: What Mode of Returned Value to Use 335 The Assignment Operator 336 Overloading the Increment and Decrement Operators 337 Overloading the Array Operator [ ] 337 Overloading Based on L-Value versus R-Value 341 CHAPTER SUMMARY 342 ANSWERS TO SELF-TEST EXERCISES 342 PROGRAMMING PROJECTS 345 08_CH08.fm Page 301 Wednesday, August 13, 2003 1:02 PM 8 Operator Overloading, Friends, and References Eternal truths will be neither true nor eternal unless they have fresh meaning for every new social situation. Franklin D. Roosevelt, Address at the University of Pennsylvania [September 20, 1940] INTRODUCTION This chapter discusses a number of tools to use when defining classes. The first tool is operator overloading, which allows you to overload operators, such as + and == , so that they apply to objects of the classes you define. The second tool is the use of friend functions which are functions that are not members of a class but still have access to the private members of the class. This chapter also discusses how to provide automatic type conversion from other data types to the classes you define. If you have not yet covered arrays (Chapter 5), you should skip the subsec- tion of 8.3 entitled Overloading the Array Operator [ ] . It covers a topic that may not make sense unless you know about array basics. Basic Operator Overloading He’s a smooth operator. Line from a song by Sade (written by Sade Adu and Ray St. John) Operators such as + , - , % , == , and so forth are nothing but functions that are used with a slightly different syntax. We write x + 7 rather than +(x, 7) , but the + operator is a function that takes two arguments (often called operands rather than arguments) and returns a single value. As such, operators are not really necessary. We could make do with +(x, 7) or even add(x, 7) . Oper- ands are an example of what is often called syntactic sugar , meaning a slightly different syntax that people like. However, people are very comfortable with the usual operator syntax, x + 7 , that C++ uses for types such as int and dou- ble . And one way to view a high-level language, such as C++, is as a way to make people comfortable with programming computers. Thus, this syntactic sugar is probably a good idea; at the least, it is a well-entrenched idea. In C++ you can overload the operators, such as + and == , so that they work with oper- ands in the classes you define. The way to overload an operator is very similar to the way you overload a function name. The details are best explained through an example. 8.1 operators and functions operand syntactic sugar 08_CH08.fm Page 302 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 303 ■ OVERLOADING BASICS Display 8.1 contains the definition of a class whose values are amounts of U.S. money, such as $9.99 or $1567.29. The class has a lot in common with the BankAccount class we defined in Display 7.2. It represents amounts of money in the same way, as two int s for the dollars and cents parts. It has the same private helping functions. Its construc- tors and accessor and mutator functions are similar to those of the class BankAccount . What is truly new about this Money class is that we have overloaded the plus sign and the minus sign so they can be used to add or subtract two objects of the class Money , and we have overloaded the == sign so it can be used to compare two objects of the class Money to see if they represent the same amount of money. Let’s look at these overloaded operators. You can overload the operator + (and many other operators) so that it will accept arguments of a class type. The difference between overloading the + operator and defin- ing an ordinary function involves only a slight change in syntax: You use the symbol + as the function name and precede the + with the keyword operator . The operator dec- laration (function declaration) for the plus sign is as follows: const Money operator +(const Money& amount1, const Money& amount2); The operands (arguments) are both constant reference parameters of type Money . The operands can be of any type, as long as at least one is a class type. In the general case, operands may be call-by-value or call-by-reference parameters and may have the const modifier or not. However, for efficiency reasons, constant call by reference is usually used in place of call by value for classes. In this case the value returned is of type Money , but in the general case the value returned can be of any type, including void . The const before the returned type Money will be explained later in this chapter. For now, you can safely ignore that const . Note that the overloaded binary operators + and - are not member operators (mem- ber functions) of the class Money and therefore do not have access to the private mem- bers of the class Money . That is why the definition for the overloaded operators uses accessor and mutator functions. Later in this chapter we will see other ways of over- loading an operand, including overloading it as a member operator. Each of the differ- ent ways of overloading an operator has its advantages and disadvantages. The definitions of the overloaded binary operators + and - are perhaps a bit more complicated than you might expect. The extra details are there to cope with the fact that amounts of money can be negative. The unary minus sign operator - is discussed in the subsection Overloading Unary Operators , later in this chapter. The operator == is also overloaded so that it can be used to compare two objects of the class Money . Note that the type returned is bool so that == can be used to make comparisons in the usual ways, such as in an if-else statement. how to overload an operator 08_CH08.fm Page 303 Wednesday, August 13, 2003 1:02 PM . Friends, and References 8.1 BASIC OPERATOR OVERLOADING 302 Overloading Basics 303 Tip: A Constructor Can Return an Object 308 Returning by const Value 309 Tip: Returning Member Variables of a Class. usual operator syntax, x + 7 , that C++ uses for types such as int and dou- ble . And one way to view a high-level language, such as C++, is as a way to make people comfortable. 8.1 operators and functions operand syntactic sugar 08_CH08.fm Page 302 Wednesday, August 13, 2003 1:02 PM Basic Operator Overloading 303 ■ OVERLOADING BASICS Display 8.1 contains the definition

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