© 2005 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. This material is protected under all copyright laws as they currently exist. No portion of this material may be reproduced, in any form or by any means, without permission in writing from the publisher. For the exclusive use of adopters of the book C++ How to Program, 5th Edition, by Deitel and Deitel. ISBN 0-13-185757-6.
10 Classes: A Deeper Lo Look, Part 2 But what, to serve our private ends, Forbids the cheating of our friends? —Charles Churchill
Instead of this absurd division into sexes they ought to class people as static and dynamic. —Evelyn Waugh
Have no friends not equal to yourself. —Confucius
OBJECTIVES In this chapter you will learn: ■
To specify const (constant) objects and const member functions.
■
To create objects composed of other objects. ob jects.
■
To use friend functions and friend classes.
■
To use the this pointer.
■
To create and destroy objects dynamically with operators new and delete, respectively.
■
To use static data members and member functions.
■
The concept of a container class.
■
■
The notion of iterator classes that walk through the elements of container classes. To use proxy classes to hide implementation details from a class’s clients.
524
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
Self-Review Exercises 10.1
Fill in the blanks in each of the following: a) must be used to initialize constant members of a class. ANS : member initializers. b) A nonmember nonmember function function must be declared declared as a(n) of a class to have access to that class’s private data members. ANS : friend. c) The operator dynamically dynamically allocates allocates memory memory for an object of a specified specified type and returns a to that type. ANS : new, pointer. d) A constant constant object must be ; it cannot be modified modified after it is created. created. ANS : initialized. e) A(n) data member member represents represents class-wide class-wide information. information. ANS : static. f) An object’s object’s non-stat non-static ic member member functions functions have have access access to a “self “self pointer” pointer” to the the object object called the pointer. ANS : this. g) The keyword specifies specifies that an object or variable variable is not modifiable modifiable after it is initialized. ANS : const. h) If a member member initialize initializerr is not provided provided for a member member object object of a class, the the object's object's is called. ANS : default constructor. i) A memb member er functi function on shoul should d be declar declared ed static if it does not access class members. ANS : non-static. j) Member objects are constructed their enclosing class object. ANS : before. k) The operator operator reclaims reclaims memory previously previously allocated allocated by new. ANS : delete.
10.2
Find the errors in the following class and explain how to correct them: class Example { public: Example ( int y = 10 ) : data( y ) { // empty body } // end Example constructor int getIncrementedData() const { return data++; } // end function getIncrementedData static int getCount() { cout << "Data is " << " << data << endl; return count; } // end function getCount private: int data;
Exercises
525
static int count; }; // end class Example
Error: The class definition for Example has two errors. The first occurs in function getIncrementedData. The function is declared const, but it modifies the object. Correction: To correct the first error, remove the const keyword from the definition of getIncrementedData. Error: The second error occurs in function getCount. This function is declared static, so it is not allowed to access any non-static member of the class. Correction: To correct the second error, remove the output line from the getCount definition.
ANS :
Exercises Compare and contrast dynamic memory allocation and deallocation operators new, new [], delete and delete []. ANS : Operator new creates an object and dynamically allocates space in memory for that object. Operator delete destroys a dynamically allocated object and frees the space that was occupied by the object. Operators new [] and delete [] are used to allocate and deallocate arrays dynamically. 10.3
Explain the notion of friendship in C++. Explain the negative aspects of friendship as described in the text. ANS : Functions that are declared as friends of a class have access to that class’s private and protected members. Some people in the object-oriented programming community prefer not to use friend functions. Such people believe friendship corrupts information hiding and weakens the value of the object-oriented design approach, because friend functions can directly access a class’s implementation details that are supposed to be hidden. 10.4
Can a correct Time class definition include both of the following constructors? If not, explain why not. 10.5
Time( int int h h = 0, int int m m = 0, int int s s = 0 ); Time(); ANS :
No. There is ambiguity between the two constructors. When a call is made to the default constructor, the compiler cannot determine which one to use because both c onstructors can be called with no arguments.
10.6
What happens when a return type, even void, is specified for a constructor or destructor? t ype for a conco n ANS : A compilation error occurs. A programmer cannot specify a return type structor or destructor.
10.7
Modify class Date in Fig. 10.10 10.10 to have the following following capabilities: capabilities: a) Output Output the date date in multi multiple ple form formats ats such such as DDD YYYY MM/DD/YY June 14, 1992
b) Use overl overload oaded ed constru constructor ctorss to create create Date objects initialized with dates of the formats in part (a).
526
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
c) Create a Date constructor that reads the system sy stem date using the standard library functions of the header and sets the Date members. (See your compiler’s reference documentation or www.cplusplus.com/ref/ctime/index.html for information on the functions in header .) In Chapter 11, we will be able able to create operators for testing the equality of two dates and for comparing dates to determine whether one date is prior to, or after, another. another. ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
1 2 3
// Exercise 10.7 Solution: Date.h // Date class definition; Member functions defined in Date.cpp #ifndef DATE_H #define DATE_H #include #include using std::string; using std::string; class Date class Date { public: public : Date(); // default constructor uses functions to set date Date( int int, , int int ); ); // constructor using ddd yyyy format Date( int int, , int int, , int int ); ); // constructor using dd/mm/yy format Date( string, int int, , int int ); ); // constructor using Month dd, yyyy format void setDay( void setDay( int int ); ); // set the day void setMonth( void setMonth( int int ); ); // set the month void print() void print() const const; ; // print date in month/day/year format void printDDDYYYY() void printDDDYYYY() const const; ; // print date in ddd yyyy format void printMMDDYY() void printMMDDYY() const const; ; // print date in mm/dd/yy format void printMonthDDYYYY() void printMonthDDYYYY() const const; ; // print date in Month dd, yyyy format ~Date(); // provided to confirm destruction order private: private : int month; int month; // 1-12 (January-December) int day; int day; // 1-31 based on month int year; int year; // any year // utility functions int checkDay( int int checkDay( int ) ) const const; ; // check if day is proper for month and year int daysInMonth( int daysInMonth( int int ) ) const const; ; // returns number of days in given month bool isLeapYear() bool isLeapYear() const const; ; // indicates whether date is in a leap year int convertDDToDDD() int convertDDToDDD() const const; ; // get 3-digit day based on month and day void setMMDDFromDDD( void setMMDDFromDDD( int int ); ); // set month and day based on 3-digit day string convertMMToMonth( int int ) ) const const; ; // convert mm to month name void setMMFromMonth( void setMMFromMonth( string ); // convert month name to mm int convertYYYYToYY() int convertYYYYToYY() const const; ; // get 2-digit year based on 4-digit year void setYYYYFromYY( void setYYYYFromYY( int int ); ); // set year based on 2-digit year }; // end class Date #endif
// Exercise 10.7 Solution: Date.cpp // Member-function definitions for class Date. #include #include
Exercises
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
527
using std::cout; using std::cout; using std::endl; using std::endl; #include #include using std::setw; using std::setw; using std::setfill; using std::setfill; #include #include using std::time; using std::time; using std::localtime; using std::localtime; using std::tm; using std::tm; using std::time_t; using std::time_t; #include "Date.h" // include Date class definition // default constructor that sets date using functions Date::Date() { // pointer of type struct tm which holds calendar time components struct tm tm *ptr; *ptr; time_t t time_t t = time( 0 ); // determine current calendar time // convert current calendar time pointed to by t into // broken down time and assign it to ptr ptr = localtime( &t ); day = ptr->tm_mday; // broken down day of month month = 1 + ptr->tm_mon; // broken down month since January year = ptr->tm_year + 1900 1900; ; // broken down year since 1900 } // end Date constructor // constructor that takes date in ddd yyyy format Date::Date( int int ddd, ddd, int int yyyy yyyy ) { year = yyyy; // could validate setMMDDFromDDD( ddd ); // set month and day based on ddd } // end Date constructor // constructor that takes date in mm/dd/yy format Date::Date( int int mm, mm, int int dd, dd, int int yy yy ) { setYYYYFromYY( yy ); // set 4-digit year based on yy setMonth( mm ); // validate and set the month setDay( dd ); // validate and set the day } // end Date constructor // constructor that takes date in Month dd, yyyy format Date::Date( string monthName, int int dd, dd, int int yyyy yyyy ) { setMMFromMonth( monthName ); // set month based on month name setDay( dd ); // validate and set the day year = yyyy; // could validate } // end Date constructor
528
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
// validate and store the day void Date::setDay( void Date::setDay( int int d d ) { day = checkDay( d ); // validate the day } // end function setDay // validate and store the month void Date::setMonth( void Date::setMonth( int int m m ) { if ( if ( m > 0 && m <= 12 12 ) ) // validate the month month = m; else { month = 1; // invalid month set to 1 cout << "Invalid month (" << (" << m << ") set to 1.\n"; 1.\n"; } // end else } // end function setMonth // print Date object in form: month/day/year void Date::print() void Date::print() const { cout << month << '/' '/' << << day << '/' '/' << << year << endl; } // end function print // print Date object in form: ddd yyyy void Date::printDDDYYYY() void Date::printDDDYYYY() const { cout << convertDDToDDD() << ' ' << ' << year << endl; } // end function printDDDYYYY // print Date object in form: mm/dd/yy void Date::printMMDDYY() void Date::printMMDDYY() const { cout << setw( 2 ) << setfill( '0' '0' ) ) << month << '/' << setw( 2 ) << setfill( '0' '0' ) ) << day << '/' << setw( 2 ) << setfill( '0' '0' ) ) << convertYYYYToYY() << endl; } // end function printMMDDYY // print Date object in form: Month dd, yyyy void Date::printMonthDDYYYY() void Date::printMonthDDYYYY() const { cout << convertMMToMonth( month ) << ' ' << ' << day << ", " << " << year << endl; } // end function printMonthDDYYYY // output Date object to show when its destructor is called Date::~Date() { cout << "Date object destructor for date "; "; print(); cout << endl; } // end ~Date destructor // utility function to confirm proper day value based on // month and year; handles leap years, too
Exercises
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
529
int Date::checkDay( int int Date::checkDay( int testDay testDay ) const { // determine whether testDay is valid for specified month if ( if ( testDay > 0 && testDay <= daysInMonth( month ) ) return testDay; return testDay; // February 29 check for leap year if ( if ( month == 2 && testDay == 29 29 && && isLeapYear() ) return testDay; return testDay; cout << "Invalid day (" << (" << testDay << ") set to 1.\n"; 1.\n"; return 1; // leave object in consistent state if bad value } // end function checkDay // return the number of days in a month int Date::daysInMonth( int Date::daysInMonth( int int m m ) const { if ( if ( isLeapYear() && m == 2 ) return 29 29; ; static const int int daysPerMonth[ daysPerMonth[ 13 13 ] ] = { 0, 31 31, , 28 28, , 31 31, , 30 30, , 31 31, , 30 30, , 31 31, , 31 31, , 30 30, , 31 31, , 30 30, , 31 31 }; }; return daysPerMonth[ m ]; return daysPerMonth[ } // end function daysInMonth // test for a leap year bool Date::isLeapYear() bool Date::isLeapYear() const { if ( if ( year % 400 400 == == 0 || ( year % 4 == 0 && year % 100 100 != != 0 ) ) return true true; ; else return false false; ; } // end function isLeapYear // calculate 3-digit day based on Date object's current month and day int Date::convertDDToDDD() int Date::convertDDToDDD() const { int ddd int ddd = 0; // for each month that has passed, add days to ddd for ( for ( int int i i = 1; i < month; i++ ) ddd += daysInMonth( i ); // add days from current month ddd += day; return ddd; return ddd; } // end function convertDDToDDD // set month and day based on 3-digit day void Date::setMMDDFromDDD( void Date::setMMDDFromDDD( int int ddd ddd ) { int dayTotal int dayTotal = 0; int m; int m;
530
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
for ( m = 1; m <= 12 for ( 12 && && ( dayTotal + daysInMonth( m ) ) < ddd; m++ ) dayTotal += daysInMonth( m ); setMonth( m ); setDay( ddd - dayTotal ); } // end function setMMDDFromDDD // utility function to convert month number to month name string Date::convertMMToMonth( int int mm mm ) const { static const const string string months[] = { "" "", , "January" "January", , "February" "February", , "March" "March", , "April" "April", , "May" "May", , "June" "June", , "July", "July" , "August" "August", , "September" "September", , "October" "October", , "November" "November", , "December" "December" }; }; return months[ mm ]; return months[ } // end function convertMMToMonth // set month number based on month name void Date::setMMFromMonth( void Date::setMMFromMonth( string m ) { bool matchFound bool matchFound = false false; ; // loop for each month, checking for a match for ( for ( int int i i = 1; i <= 12 12 && && !matchFound; i++ ) { string tempMonth = convertMMToMonth( i ); if ( tempMonth == m ) if ( { setMonth( i ); matchFound = true true; ; } // end if } // end for if ( !matchFound ) if ( { cout << "Invalid month name (" << (" << month << "). month set to 1.\n"; 1.\n"; setMonth( 1 ); // leave object in consistent state if bad value } // end if } // end function setMMFromMonth // utility function to convert 4-digit year to 2-digit year int Date::convertYYYYToYY() int Date::convertYYYYToYY() const { // if year is in 2000s, subtract 2000 // else, assume year is in the 1900s and subtract 1900 return ( return ( year >= 2000 2000 ? ? year - 2000 2000 : : year - 1900 1900 ); ); } // end function convertYYYYtoYY // utility function to convert 2-digit year to 4-digit year void Date::setYYYYFromYY( void Date::setYYYYFromYY( int int yy yy ) { // if yy is less than 7, assume its in the 2000s // if yy is greater than or equal to 7, assume it's in the 1900s
Exercises
224 225
year = ( yy < 7 ? yy + 2000 2000 : : yy + 1900 1900 ); ); } // end function setYYYYFromYY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
// Exercise 10.7 Solution: ex10_07.cpp // Driver program for class Date. #include #include using std::cout; using std::cout; using std::endl; using std::endl;
531
#include "Date.h" // include Date class definition int main() int main() { Date date1( Date date2( Date date3( Date date4;
256, 1999 256, 1999 ); ); // initialize using ddd yyyy format 3, 25 25, , 04 04 ); ); // initialize using mm/dd/yy format "September", "September" , 1, 2000 2000 ); ); // "month" dd, yyyy format // initialize to current date with default constructor
// print Date objects in default format date1.print(); date2.print(); date3.print(); date4.print(); cout << '\n' '\n'; ;
// print Date objects in 'ddd yyyy' format date1.printDDDYYYY(); date2.printDDDYYYY(); date3.printDDDYYYY(); date4.printDDDYYYY(); cout << '\n' '\n'; ;
// print Date objects in 'mm/dd/yy' format date1.printMMDDYY(); date2.printMMDDYY(); date3.printMMDDYY(); date4.printMMDDYY(); cout << '\n' '\n'; ;
// print Date objects in '"month" d, yyyy' format date1.printMonthDDYYYY(); date2.printMonthDDYYYY(); date3.printMonthDDYYYY(); date4.printMonthDDYYYY(); cout << endl;
return 0; } // end main
Chap Ch apte terr 10
532
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
9/13/1999 3/25/2004 9/1/2000 12/14/2004 256 1999 85 2004 245 2000 349 2004 09/13/99 03/25/04 09/01/00 12/14/04 September 13, 1999 March 25, 2004 September 1, 2000 December 14, 2004 Date object destructor for date 12/14/2004 Date object destructor for date 9/1/2000 Date object destructor for date 3/25/2004 Date object destructor for date 9/13/1999
Create a SavingsAccount class. Use a static data member annualInterestRate to store the annual interest rate for each of the savers. Each member of the class contains a private data member savingsBalance indicating the amount the saver currently has on deposit. Provide member function calculateMonthlyInterest that calculates the monthly interest by multiplying the balance by annualInterestRate divided by 12; this interest should be added to savingsBalance. Provide a static member function modifyInterestRate that sets the static annualInterestRate to a new value. Write a driver program to test class SavingsAccount. Instantiate two different objects of class SavingsAccount, saver1 and saver2, with balances of $2000.00 and $3000.00, respectively. Set the annualInterestRate to 3 percent. Then calculate the monthly interest and print the new balances for each of the savers. Then set the annualInterestRate to 4 percent, calculate the next month’s interest and print the new balances for each of the savers. 10.8
ANS :
1 2 3 4 5 6 7 8 9 10 11 12
// SavingsAccount.h // Header file for class SavingsAccount. #ifndef SAVINGS_ACCOUNT_H #define SAVINGS_ACCOUNT_H class SavingsAccount class SavingsAccount { public: public : // constructor sets balance to value greater than or equal to zero SavingsAccount( double double b b ) { savingsBalance = ( b >= 0.0 0.0 ? ? b : 0.0 0.0 ); );
Exercises
13 14 15 16 17 18 19 20 21 22 23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
1 2 3 4 5 6 7 8
533
} // end SavingsAccount constructor void calculateMonthlyInterest(); // calculate interest; add to balance void static void void modifyInterestRate( modifyInterestRate( double double ); ); void printBalance() void printBalance() const const; ; private: private : double savingsBalance; double savingsBalance; // the account balance static double double annualInterestRate; annualInterestRate; // the interest rate of all accounts }; // end class SavingsAccount #endif
// Exercise 10.8 Solution: SavingsAccount.cpp // Member-function defintions for class SavingsAccount. #include #include using std::cout; using std::cout; using std::fixed; using std::fixed; #include #include using std::setprecision; using std::setprecision; #include "SavingsAccount.h" // SavingsAccount class definition // initialize static data member double SavingsAccount::annualInterestRate double SavingsAccount::annualInterestRate = 0.0 0.0; ; // calculate monthly interest for this savings account void void SavingsAccount::calculateMonthlyInterest() { savingsBalance += savingsBalance * ( annualInterestRate / 12.0 12.0 ); ); } // end function calculateMonthlyInterest // function for modifying static member variable annualInterestRate void void SavingsAccount::modifyInterestRate( double double i i ) { annualInterestRate = ( i >= 0.0 0.0 && && i <= 1.0 1.0 ) ) ? i : 0.03 0.03; ; } // end function modifyInterestRate // prints balance of the savings account void void SavingsAccount::printBalance() const { cout << fixed << '$' '$' << << setprecision( 2 ) << savingsBalance; } // end function printBalance
// Exercise 10.8 Solution: ex10_08.cpp // Driver program for class SavingsAccount. #include #include using std::cout; using std::cout; using std::endl; using std::endl; #include #include using std::setw; using std::setw;
534
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
#include "SavingsAccount.h" // SavingsAccount class definition int main() int main() { SavingsAccount saver1( 2000.0 2000.0 ); ); SavingsAccount saver2( 3000.0 ); 3000.0 );
SavingsAccount::modifyInterestRate( .03 .03 ); ); // change interest rate
cout << "Initial balances:\nSaver 1: "; "; saver1.printBalance(); cout << "\tSaver 2: "; "; saver2.printBalance();
saver1.calculateMonthlyInterest(); saver2.calculateMonthlyInterest();
cout << "\n\nBalances after 1 month's interest applied at .03:\n" << "Saver 1: "; "; saver1.printBalance(); cout << "\tSaver 2: "; "; saver2.printBalance();
SavingsAccount::modifyInterestRate( .04 .04 ); ); // change interest rate saver1.calculateMonthlyInterest(); saver2.calculateMonthlyInterest();
cout << "\n\nBalances after 1 month's interest applied at .04:\n" << "Saver 1: "; "; saver1.printBalance(); cout << "\tSaver 2: "; "; saver2.printBalance(); cout << endl; return 0; } // end main
Initial balances: Saver 1: $2000.00
Saver 2: $3000.00
Balances after 1 month's interest applied at .03: Saver 1: $2005.00 Saver 2: $3007.50 Balances after 1 month's interest applied at .04: Saver 1: $2011.68 Saver 2: $3017.53
Create class IntegerSet for which each object can hold integers in the range 0 through 100. A set is represented internally as an array of ones and zeros. Array element a[ i ] is 1 if integer i is in the set. Array element a[ j ] is 0 if integer j is not in the set. The default constructor initializes a set to the so-called “empty set,” i.e., a set whose array representation contains all zeros. Provide Provide member functions for the common set operations. For example, provide a unionOfSets member function that creates a third set that is the set-theoretic union of two existing sets (i.e., an element of the third set’s array is set to 1 if that element is 1 in either or both of the existing sets, and an element of the third set’s array is set to 0 if that element is 0 in each of the existing sets). 10.9
Exercises
535
Provide an intersectionOfSets member function which creates a third set which is the settheoretic intersection of two existing sets (i.e., an element of the third set’s array is set to 0 if that element is 0 in either or both of the existing sets, and an element of the third set’ s et’ss array is set se t to 1 if that element is 1 in each of the existing sets). Provide an insertElement member function that inserts a new integer k into into a set (by setting a[ k ] to 1). Provide a deleteElement member function that deletes integer m (by setting a[ m ] to 0). Provide a printSet member function that prints a set as a list of numbers separated by spaces. Print only those elements that are present in the set (i.e., their position in the array has a value of 1). Print --- for an empty set. Provide an isEqualTo member function that determines whether two sets are equal. Provide an additional constructor that receives an array of integers and the size of that array and uses the array to initialize a set object. Now write a driver program to test your IntegerSet class. Instantiate several IntegerSet objects. Test Test that all your member functions work properly. ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// Exercise 10.9 Solution: IntegerSet.h // Header file for class IntegerSet #ifndef INTEGER_SET_H #define INTEGER_SET_H class IntegerSet class IntegerSet { public: public : // default constructor IntegerSet() { emptySet(); // set all elements of set to 0 } // end IntegerSet constructor
IntegerSet( int int [], [], int int ); ); // constructor that takes an initial set IntegerSet unionOfSets( const const IntegerSet& IntegerSet& ); IntegerSet intersectionOfSets( const const IntegerSet& IntegerSet& ); void emptySet(); void emptySet(); // set all elements of set to 0 void inputSet(); void inputSet(); // read values from user void insertElement( void insertElement( int int ); ); void deleteElement( void deleteElement( int int ); ); void printSet() void printSet() const const; ; bool isEqualTo( bool isEqualTo( const const IntegerSet& IntegerSet& ) const const; ; private: private : int set[ int set[ 101 101 ]; ]; // range of 0 - 100
// determines a valid entry to the set int validEntry( int validEntry( int int x x ) const { return ( return ( x >= 0 && x <= 100 100 ); ); } // end function validEntry }; // end class IntegerSet #endif
536
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
// Exercise 10.9 Solution: IntegerSet.cpp // Member-function definitions for class IntegerSet. #include #include using std::cout; using std::cout; using std::cin; using std::cin; using std::cerr; using std::cerr; #include #include using std::setw; using std::setw; #include "IntegerSet.h" // IntegerSet class definition // constructor creates a set from array of integers IntegerSet::IntegerSet( int int array[], array[], int int size) size) { emptySet(); for ( int for ( int i i = 0; i < size; i++ ) insertElement( array[ i ] ); } // end IntegerSet constructor // initializes a set to the empty set void IntegerSet::emptySet() void IntegerSet::emptySet() { for ( for ( int int y y = 0; y < 101 101; ; y++ ) set[ y ] = 0; } // end function emptySet // input a set from the user void IntegerSet::inputSet() void IntegerSet::inputSet() { int number; int number; do { cout << "Enter an element (-1 to end): "; "; cin >> number; if ( if ( validEntry( number ) ) set[ number ] = 1; else if if ( ( number != -1 -1 ) ) cerr << "Invalid Element\n"; Element\n"; } while while ( ( number != -1 -1 ); ); // end do...while cout << "Entry complete\n"; complete\n"; } // end function inputSet // prints the set to the output stream void IntegerSet::printSet() void IntegerSet::printSet() const { int x int x = 1; bool empty bool empty = true true; ; // assume set is empty cout << '{' << '{'; ;
Exercises
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
for (int for ( int u u = 0; u < 101 101; ; u++ ) { if ( if ( set[ u ] ) { cout << setw( 4 ) << u << ( x % 10 10 == == 0 ? "\n" "\n" : : "" "" ); ); empty = false false; ; // set is not empty x++; } // end if } // end for if ( if ( empty ) cout << setw( 4 ) << "---" "---"; ; // display an empty set
cout << setw( 4 ) << "}" "}" << << '\n' '\n'; ; } // end function printSet // returns the union of two sets IntegerSet IntegerSet::unionOfSets( const const IntegerSet IntegerSet &r ) { IntegerSet temp; // if element is in either set, add to temporary set for ( for ( int int n n = 0 = 0; ; n < 101 101; ; n++ ) if ( if ( set[ n ] == 1 || r.set[ n ] == 1 ) temp.set[ n ] = 1; return temp; return temp; } // end function unionOfSets // returns the intersection of two sets IntegerSet IntegerSet::intersectionOfSets( const const IntegerSet IntegerSet &r ) { IntegerSet temp; // if element is in both sets, add to temporary set for ( for ( int int w w = 0; w < 101 101; ; w++ ) if ( if ( set[ w ] == 1 && r.set[ w ] == 1 ) temp.set[ w ] = 1; return temp; return temp; } // end function intersectionOfSets // insert a new integer into this set void IntegerSet::insertElement( void IntegerSet::insertElement( int int k k ) { if ( if ( validEntry( k ) ) set[ k ] = 1; else cerr << "Invalid insert attempted!\n"; attempted!\n"; } // end function insertElement // removes an integer from this set void IntegerSet::deleteElement( void IntegerSet::deleteElement( int int m m ) { if ( if ( validEntry( m ) )
537
538
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
111 112 113 114 115 116 117 118 119 120 121 122 123 124
set[ m ] = 0; else cerr << "Invalid delete attempted!\n"; attempted!\n"; } // end function deleteElement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
// Exercise 10.9 Solution: ex10_09.cpp // Driver program for class IntegerSet. #include #include using std::cout; using std::cout; using std::endl; using std::endl;
// determines if two sets are equal bool IntegerSet::isEqualTo( bool IntegerSet::isEqualTo( const const IntegerSet IntegerSet &r ) const { for ( for ( int int v v = 0; v < 101 101; ; v++ ) if ( if ( set[ v ] != r.set[ v ] ) return false false; ; // sets are not-equal return true true; ; // sets are equal } // end function isEqualTo
#include "IntegerSet.h" // IntegerSet class definition int main() int main() { IntegerSet IntegerSet IntegerSet IntegerSet
a; b; c; d;
cout << "Enter set A:\n"; A:\n"; a.inputSet(); cout << "\nEnter set B:\n"; B:\n"; b.inputSet(); c = a.unionOfSets( b ); d = a.intersectionOfSets( b ); cout << "\nUnion of A and B is:\n"; is:\n"; c.printSet(); cout << "Intersection of A and B is:\n"; is:\n"; d.printSet(); if ( if ( a.isEqualTo( b ) ) cout << "Set A is equal to set B\n"; B\n"; else cout << "Set A is not equal to set B\n"; B\n";
cout << "\nInserting 77 into set A...\n"; A...\n"; a.insertElement( 77 77 ); ); cout << "Set A is now:\n"; now:\n"; a.printSet(); cout << "\nDeleting 77 from set A...\n"; A...\n"; a.deleteElement( 77 77 ); ); cout << "Set A is now:\n"; now:\n";
Exercises
40 41 42 43 44 45 46 47 48 49 50 51 52
539
a.printSet(); const int int arraySize arraySize = 10 10; ; int intArray[ int intArray[ arraySize ] = { 25 25, , 67 67, , 2, 9, 99 99, , 105 105, , 45 45, , -5 -5, , 100 100, , 1 }; IntegerSet e( intArray, arraySize );
cout << "\nSet e is:\n"; is:\n"; e.printSet(); cout << endl;
return 0; } // end main
Enter Enter Enter Enter Enter Enter Entry
set A: an element an element an element an element an element complete
(-1 (-1 (-1 (-1 (-1
to to to to to
end): end): end): end): end):
45
Enter Enter Enter Enter Enter Enter Entry
set B: an element an element an element an element an element complete
(-1 (-1 (-1 (-1 (-1
to to to to to
end): end): end): end): end):
34
76 34 6 -1
8 93 45 -1
Union of A and B is: { 6 8 34 45 76 93 } Intersection of A and B is: { 34 45 } Set A is not equal to set B Inserting 77 into set A... Set A is now: { 6 34 45 76 77 } Deleting 77 from set A... Set A is now: { 6 34 45 76 } Invalid insert attempted! Invalid insert attempted! Set e is: { 1 2
9
25
45
67
99 100
}
10.18–10.19 .19 to represent represent the 10.10 It would be perfectly reasonable for the Time class of Figs. 10.18–10 time internally as the number of seconds since midnight rather than the three integer values hour, minute and second. Clients could use the same public methods and get the same results. Modify
540
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
the Time class of Fig. 10.18 to implement the time as the number of seconds since midnight and show that there is no visible change in functionality to the clients of the class. [Note: This exercise nicely demonstrates the virtues of implementation hiding.] ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Exercise 10.10 Solution: Time.h // Time class definition; Member functions defined in Time.cpp. #ifndef TIME_H #define TIME_H class Time class Time { public: public : Time( int int = = 0, int int = = 0 0, , int int = = 0 ); // default constructor // set functions (the Time & return types enable cascading) Time &setTime( int int, , int int, , int int ); ); // set hour, minute, second Time &setHour( int int ); ); // // set hour Time &setMinute( int int ); ); // set minute Time &setSecond( int int ); ); // set second // get functions (normally declared const) int getHour() int getHour() const const; ; // return hour int getMinute() int getMinute() const const; ; // return minute int getSecond() int getSecond() const const; ; // return second // print functions (normally declared const) void printUniversal() void printUniversal() const const; ; // print universal time void printStandard() void printStandard() const const; ; // print standard time private: private : int totalSeconds; int totalSeconds; // number of seconds since midnight }; // end class Time #endif
// Exercise 10.10 Solution: Time.cpp // Member-function definitions for Time class. #include #include using std::cout; using std::cout; #include #include using std::setfill; using std::setfill; using std::setw; using std::setw; #include "Time.h" // Time class definition // constructor function to initialize private data; // calls member function setTime to set variables; // default values are 0 (see class definition) Time::Time( int int hr, hr, int int min, min, int int sec sec ) { setTime( hr, min, sec ); } // end Time constructor
Exercises
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
541
// set values of hour, minute, and second Time &Time::setTime( int int h, h, int int m, m, int int s s ) // note Time & return { setHour( h ); setMinute( m ); setSecond( s ); return * return *this this; ; // enables cascading } // end function setTime // set hour value Time &Time::setHour( int int h h ) // note Time & return { int hours int hours = ( h >= 0 && h < 24 24 ) ) ? h : 0; totalSeconds = ( hours * 3600 3600 ) ) + ( getMinute() * 60 60 ) ) + getSecond(); return * return *this this; ; // enables cascading } // end function setHour // set minute value Time &Time::setMinute( int int m m ) // note Time & return { int minutes int minutes = ( m >= 0 && m < 60 60 ) ) ? m : 0; totalSeconds = ( getHour() * 3600 3600 ) ) + ( minutes * 60 60 ) ) + getSecond(); return * return *this this; ; // enables cascading } // end function setMinute // set second value Time &Time::setSecond( int int s s ) // note Time & return { int seconds int seconds = ( s >= 0 && s < 60 60 ) ) ? s : 0; totalSeconds = ( getHour() * 3600 3600 ) ) + ( getMinute() * 60 60 ) ) + seconds; return * return *this this; ; // enables cascading } // end function setSecond // get hour value int Time::getHour() int Time::getHour() const { return ( return ( totalSeconds / 3600 3600 ); ); } // end function getHour // get minute value int Time::getMinute() int Time::getMinute() const { return ( return ( ( totalSeconds % 3600 3600 ) ) / 60 60 ); ); } // end function getMinute // get second value int Time::getSecond() int Time::getSecond() const { return ( return ( ( totalSeconds % 3600 3600 ) ) % 60 60 ); ); } // end function getSecond // print Time in universal-time format (HH:MM:SS) void Time::printUniversal() void Time::printUniversal() const {
542
Chap Ch apte terr 10
Clas Cl asse ses: s: A De Deep eper er Loo Look, k, Par Partt 2
74 75 76 77 78 79 80 81 82 83 84 85
cout << setfill( '0' '0' ) ) << setw( 2 ) << getHour() << ":" << setw( 2 ) << getMinute() << ":" ":" << << setw( 2 ) << getSecond(); } // end function printUniversal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// Exercise 10.10 Solution: ex10_10.cpp // Driver program for Time class. #include #include using std::cout; using std::cout; using std::endl; using std::endl;
// print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() void Time::printStandard() const { int hour int hour = getHour(); cout << ( ( hour == 0 || hour == 12 12 ) ) ? 12 12 : : hour % 12 12 ) ) << ":" ":" << << setfill( '0' '0' ) ) << setw( 2 ) << getMinute() << ":" ":" << << setw( 2 ) << getSecond() << ( hour < 12 12 ? ? " AM" : AM" : " PM" ); PM" ); } // end function printStandard
#include "Time.h" "Time.h" // // Time class definition int main() int main() { Time t; // create Time object
// cascaded function calls t.setHour( 18 18 ).setMinute( ).setMinute( 30 30 ).setSecond( ).setSecond( 22 22 ); );
// output time in universal and standard formats cout << "Universal time: "; "; t.printUniversal();
cout << "\nStandard time: "; "; t.printStandard(); cout << "\n\nNew standard time: "; ";
// cascaded function calls t.setTime( 20 20, , 20 20, , 20 20 ).printStandard(); ).printStandard(); cout << endl; return 0; } // end main
Universal time: 18:30:22 Standard time: 6:30:22 PM New standard time: 8:20:20 PM