Tải bản đầy đủ (.pdf) (10 trang)

Absolute C++ (4th Edition) part 28 pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (197.64 KB, 10 trang )

Constructors 273
Display 7.2 Bank Account Class
(part 5 of 5)
161 return static_cast<int>(amount);
162 }
163 //Uses cmath:
164 int BankAccount::centsPart(double amount)
165 {
166 double doubleCents = amount*100;
167 int intCents = (round(fabs(doubleCents)))%100;//% can misbehave on negatives
168 if (amount < 0)
169 intCents = -intCents;
170 return intCents;
171 }
172 //Uses cmath:
173 int BankAccount::round(double number)
174 {
175 return static_cast<int>(floor(number + 0.5));
176 }
177 double BankAccount::fraction(double percent)
178 {
179 return (percent/100.0);
180 }
S
AMPLE
D
IALOGUE
account1 initialized as follows:
Account balance: $1345.52
Rate: 2.3%
account2 initialized as follows:


Account balance: $0.00
Rate: 0%
account1 reset to the following:
Account balance: $999.99
Rate: 5.5%
Enter new data for account 2:
Enter account balance $100.00
Enter interest rate (NO percent sign): 10
account2 reset to the following:
Account balance: $100
Rate: 10%
In one year account2 will grow to:
Account balance: $110
Rate: 10%
if this does not seem clear, see
the discussion of
round in
Chapter 3, Section 3.2.
These could be regular functions rather than member functions,
but as member functions we were able to make them private.
07_CH07.fm Page 273 Wednesday, August 13, 2003 12:58 PM
274 Constructors and Other Tools
Self-Test Exercises
3. The function BankAccount::input in Display 7.2 reads the balance of the account as a
value of type
double. When the value is stored in the computer’s memory in binary form,
this can create a slight error. It would normally not be noticed and the function is good
enough for the demonstration class
BankAccount. Spending too much time on numerical
analysis would detract from the message at hand. Still, this input function is not good

enough for banking. Rewrite the function
BankAccount::input so it reads an amount
such as
78.96 as the int 76 and the three char values ’.’, ’9’, and ’6’. You can assume
the user always enters two digits for the cents in an amount, such as
99.00 instead of just
99 and nothing more. Hint: The following formula will convert a digit to the correspond-
ing
int value, such as ’6’ to 6:
static_cast<int>(digit) - static_cast<int>(’0’)

CLASS TYPE MEMBER VARIABLES
A class may have a member variable whose type is that of another class. By and large
there is nothing special that you need to do to have a class member variable, but there is
a special notation to allow for the invocation of the member variable’s constructor
within the constructor of the outer class. An example is given in Display 7.3.

The class Holiday in Display 7.3 might be used by some city police department to
help keep track of which holidays will have parking enforcement (of things such as
parking meters and one hour parking zones). It’s a highly simplified class. A real class
would have more member functions, but the class
Holiday is complete enough to illus-
trate our points.
The class
Holiday has two member variables. The member variable parkingEn-
forcement
is an ordinary member variable of the simple type bool. The member vari-
able
date is of the class type DayOfYear.
Below we have reproduced one constructor definition from Display 7.3:

Holiday::Holiday(int month, int day, bool theEnforcement)
: date(month, day), parkingEnforcement(theEnforcement)
{/*Intentionally empty*/}
Notice that we have set the member variable parkingEnforcement in the initialization
section in the usual way, namely, with
parkingEnforcement(theEnforcement)
The member variable date is a member of the class type DayOfYear. To initialize
date, we need to invoke a constructor from the class DayOfYear (the type of date). This
is done in the initialization section with the similar notation
date(month, day)
07_CH07.fm Page 274 Wednesday, August 13, 2003 12:58 PM
Constructors 275
Display 7.3 A Class Member Variable
(part 1 of 3)
1 #include <iostream>
2 #include<cstdlib>
3 using namespace std;
4 class DayOfYear
5 {
6 public:
7 DayOfYear(int monthValue, int dayValue);
8 DayOfYear(int monthValue);
9 DayOfYear( );
10 void input( );
11 void output( );
12 int getMonthNumber( );
13 int getDay( );
14 private:
15 int month;
16 int day;

17 void testDate( );
18 };
19 class Holiday
20 {
21 public:
22 Holiday( );//Initializes to January 1 with no parking enforcement
23 Holiday(int month, int day, bool theEnforcement);
24 void output( );
25 private:
26 DayOfYear date;
27 bool parkingEnforcement;//true if enforced
28 };
29 int main( )
30 {
31 Holiday h(2, 14, true);
32 cout << "Testing the class Holiday.\n";
33 h.output( );

34 return 0;
35 }
36
37 Holiday::Holiday( ) : date(1, 1), parkingEnforcement(false)
38 {/*Intentionally empty*/}
39 Holiday::Holiday(int month, int day, bool theEnforcement)
40 : date(month, day), parkingEnforcement(theEnforcement)
41 {/*Intentionally empty*/}
member variable of a class type
The class DayOfYear is the same as in Display
7.1, but we have repeated all the details you
need for this discussion.

Invocations of constructors
from the class
DayOfYear.
07_CH07.fm Page 275 Wednesday, August 13, 2003 12:58 PM
276 Constructors and Other Tools
Display 7.3 A Class Member Variable
(part 2 of 3)
42 void Holiday::output( )
43 {
44 date.output( );
45 cout << endl;
46 if (parkingEnforcement)
47 cout << "Parking laws will be enforced.\n";
48 else
49 cout << "Parking laws will not be enforced.\n";
50 }
51 DayOfYear::DayOfYear(int monthValue, int dayValue)
52 : month(monthValue), day(dayValue)
53 {
54 testDate( );
55 }
56 //uses iostream and cstdlib:
57 void DayOfYear::testDate( )
58 {
59 if ((month < 1) || (month > 12))
60 {
61 cout << "Illegal month value!\n";
62 exit(1);
63 }
64 if ((day < 1) || (day > 31))

65 {
66 cout << "Illegal day value!\n";
67 exit(1);
68 }
69 }
70
71 //Uses iostream:
72 void DayOfYear::output( )
73 {
74 switch (month)
75 {
76 case 1:
77 cout << "January "; break;
78 case 2:
79 cout << "February "; break;
80 case 3:
81 cout << "March "; break;
.
.
.
The omitted lines are in Display 6.3,
but they are obvious enough that you
should not have to look there.
07_CH07.fm Page 276 Wednesday, August 13, 2003 12:58 PM
More Tools 277
The notation date(month, day) is an invocation of the constructor for the class DayOf-
Year
with arguments month and day to initialize the member variables of date. Notice
that this notation is analogous to how you would declare a variable
date of type Day-

OfYear
. Also notice that the parameters of the larger class constructor Holiday can be
used in the invocation of the constructor for the member variable.
More Tools
Intelligence . . . is the facility of making artificial objects, especially tools
to make tools.
Henri Bergson, Creative Evolution
This section discusses three topics that, although important, did not fit easily before
here. The three topics are
const parameters for classes, inline functions, and static class
members.

THE
const
PARAMETER MODIFIER
A call-by-reference parameter is more efficient than a call-by-value parameter. A call-
by-value parameter is a local variable that is initialized to the value of its argument, so
when the function is called there are two copies of the argument. With a call-by-reference
parameter, the parameter is just a placeholder that is replaced by the argument, so there
is only one copy of the argument. For parameters of simple types, such as
int or dou-
ble
, the difference in efficiency is negligible, but for class parameters the difference in
Display 7.3 A Class Member Variable
(part 3 of 3)
82 case 11:
83 cout << "November "; break;
84 case 12:
85 cout << "December "; break;
86 default:

87 cout << "Error in DayOfYear::output. Contact software vendor.";
88 }
89 cout << day;
90 }
S
AMPLE
D
IALOGUE
Testing the class Holiday.
February 14
Parking laws will be enforced.
7.2
07_CH07.fm Page 277 Wednesday, August 13, 2003 12:58 PM
278 Constructors and Other Tools
efficiency can sometimes be important. Thus, it can make sense to use a call-by-reference
parameter rather than a call-by-value parameter for a class, even if the function does
not change the parameter.
If you are using a call-by-reference parameter and your function does not change the
value of the parameter, you can mark the parameter so that the compiler knows that
the parameter should not be changed. To do so, place the modifier
const before the
parameter type. The parameter is then called a constant parameter or constant call-
by-reference parameter. For example, in Display 7.2 we defined a class named
BankAccount for simple bank accounts. In some program you might want to write a
Boolean-valued function to test which of two accounts has the larger balance. The def-
inition of the function might be as follows:
bool isLarger(BankAccount account1, BankAccount account2)
//Returns true if the balance in account1 is greater than that
//in account2. Otherwise returns false.
{

return(account1.getBalance( ) > account2.getBalance( ));
}
This is perfectly legal. The two parameters are call-by-value parameters. However, it
would be more efficient and is more common to make the parameters constant call-by-
reference parameters, as follows:
bool isLarger(const BankAccount& account1,
const BankAccount& account2)
//Returns true if the balance in account1 is greater than that
//in account2. Otherwise, returns false.
{
return(account1.getBalance( ) > account2.getBalance( ));
}
Note that the only difference is that we made the parameter call-by-reference by adding
& and we added the const modifiers. If there is a function declaration, then the same
change must be made to the parameters in the function declaration.
Constant parameters are a form of automatic error checking. If your function defini-
tion contains a mistake that causes an inadvertent change to the constant parameter,
the compiler will issue an error message.
The parameter modifier
const can be used with any kind of parameter; however, it
is normally used only for call-by-reference parameters for classes (and for certain other
parameters whose corresponding arguments are large, such as arrays).
Suppose you invoke a member function for an object of a class, such as the class
BankAccount in Display 7.2. For example:
BankAccount myAccount;
myAccount.input( );
myAccount.output( );
constant
parameter
07_CH07.fm Page 278 Wednesday, August 13, 2003 12:58 PM

More Tools 279
Pitfall
The invocation of the member function input changes the values of the member vari-
ables in the calling object
myAccount. So the calling object behaves sort of like a call-by-
reference parameter; the function invocation can change the calling object. Sometimes,
you do not want to change the member variables of the calling object. For example, the
member function
output should not change the values of the calling object’s member
variables. You can use the
const modifier to tell the compiler that a member function
invocation should not change the calling object.
The modifier
const applies to calling objects in the same way that it applies to
parameters. If you have a member function that should not change the value of a call-
ing object, you can mark the function with the
const modifier; the computer will then
issue an error message if your function code inadvertently changes the value of the call-
ing object. In the case of a member function, the
const goes at the end of the function
declaration, just before the final semicolon, as shown below:
class BankAccount
{
public:

void output( ) const;

The modifier const should be used in both the function declaration and the function
definition, so the function definition for
output would begin as follows:

void BankAccount::output( ) const
{

The remainder of the function definition would be the same as in Display 7.2.
I
NCONSISTENT
U
SE

OF

const
Use of the const modifier is an all-or-nothing proposition. If you use const for one parameter
of a particular type, then you should use it for every other parameter that has that type and that is
not changed by the function call. Moreover, if the type is a class type, then you should also use
the
const modifier for every member function that does not change the value of its calling
object. The reason has to do with function calls within function calls. For example, consider the
following definition of the function
welcome:
void welcome(const BankAccount& yourAccount)
{
cout << "Welcome to our bank.\n"
<< "The status of your account is:\n";
yourAccount.output( );
}
const with
member
functions
07_CH07.fm Page 279 Wednesday, August 13, 2003 12:58 PM

280 Constructors and Other Tools
If you do
not
add the const modifier to the function declaration for the member function out-
put
, then the function welcome will produce an error message. The member function welcome
does not change the calling object
price. However, when the compiler processes the function
definition for
welcome, it will think that welcome does (or at least might) change the value of
const
P
ARAMETER
M
ODIFIER
If you place the modifier const before the type for a call-by-reference parameter, the parameter
is called a cc
cc
oo
oo
nn
nn
ss
ss
tt
tt
aa
aa
nn
nn

tt
tt


pp
pp
aa
aa
rr
rr
aa
aa
mm
mm
ee
ee
tt
tt
ee
ee
rr
rr
.

When you add the const you are telling the compiler that this
parameter should not be changed. If you make a mistake in your definition of the function so that
it does change the constant parameter, then the compiler will give an error message. Parameters
of a class type that are not changed by the function ordinarily should be constant call-by-reference
parameters rather than call-by-value parameters.
If a member function does not change the value of its calling object, then you can mark the func-

tion by adding the
const modifier to the function declaration. If you make a mistake in your def-
inition of the function so that it does change the calling object and the function is marked with
const, the computer will give an error message. The const is placed at the end of the function
declaration, just before the final semicolon. The heading of the function definition should also
have a
const so that it matches the function declaration.
E
XAMPLE
class Sample
{
public:
Sample( );
void input( );
void output( ) const;
private:
int stuff;
double moreStuff;
};
int compare(const Sample& s1, const Sample& s2);
Use of the const modifier is an all or nothing proposition. You should use the const modifier
whenever it is appropriate for a class parameter and whenever it is appropriate for a member
function of the class. If you do not use
const every time that it is appropriate for a class, then
you should never use it for that class.
07_CH07.fm Page 280 Wednesday, August 13, 2003 12:58 PM
More Tools 281
Self-Test Exercises
yourAccount. This is because when it is translating the function definition for welcome, all that
the compiler knows about the member function

output is the function declaration for output. If
the function declaration does not contain a
const that tells the compiler that the calling object
will not be changed, then the compiler assumes that the calling object will be changed. Thus, if
you use the modifier
const with parameters of type BankAccount, then you should also use
const with all BankAccount member functions that do not change the values of their calling
objects. In particular, the function declaration for the member function
output should include a
const.
In Display 7.4 we have rewritten the definition of the class
BankAccount given in Display 7.2, but
this time we have used the
const modifier where appropriate. In Display 7.4 we have also added
the two functions
isLarger and welcome, which we discussed earlier and which have constant
parameters.
4. Why would it be incorrect to add the modifier const, as shown below, to the declaration
for the member function
input of the class BankAccount given in Display 7.2?
class BankAccount
{
public:
void input( ) const;

5. What are the differences and the similarities between a call-by-value parameter and a con-
stant call-by-reference parameter? Declarations that illustrate these follow.
void callByValue(int x);
void callByConstReference(const int& x);
6. Given the definitions

const int x = 17;
class A
{
public:
A( );
A(int n);
int f( )const;
int g(const A& x);
private:
int i;
};
Each of the three const keywords is a promise to the compiler that the compiler will
enforce. What is the promise in each case?
07_CH07.fm Page 281 Wednesday, August 13, 2003 12:58 PM
282 Constructors and Other Tools
Display 7.4 The const Parameter Modifier
(part 1 of 3)
1 #include <iostream>
2 #include <cmath>
3 #include <cstdlib>
4 using namespace std;
5 //Data consists of two items: an amount of money for the account balance
6 //and a percentage for the interest rate.
7 class BankAccount
8 {
9 public:
10 BankAccount(double balance, double rate);
11 //Initializes balance and rate according to arguments.
12 BankAccount(int dollars, int cents, double rate);
13 //Initializes the account balance to $dollars.cents. For a negative balance both

14 //dollars and cents must be negative. Initializes the interest rate to rate percent.
15 BankAccount(int dollars, double rate);
16 //Initializes the account balance to $dollars.00 and
17 //initializes the interest rate to rate percent.
18 BankAccount( );
19 //Initializes the account balance to $0.00 and the interest rate to 0.0%.
20 void update( );
21 //Postcondition: One year of simple interest has been added to the account.
22 void input( );
23 void output( ) const;
24 double getBalance( ) const;
25 int getDollars( ) const;
26 int getCents( ) const;
27 double getRate( ) const;//Returns interest rate as a percentage.
28 void setBalance(double balance);
29 void setBalance(int dollars, int cents);
30 //Checks that arguments are both nonnegative or both nonpositive.
31 void setRate(double newRate);
32 //If newRate is nonnegative, it becomes the new rate. Otherwise, abort program.
33
34 private:
35 //A negative amount is represented as negative dollars and negative cents.
36 //For example, negative $4.50 sets accountDollars to -4 and accountCents to -50.
37 int accountDollars; //of balance
38 int accountCents; //of balance
39 double rate;//as a percent
This is class from Display 7.2
rewritten using the
const
modifier.

07_CH07.fm Page 282 Wednesday, August 13, 2003 12:58 PM

×