Display 7.4 The const Parameter Modifier part 2 of 340 int dollarsPart double amount const ; 41 int centsPart double amount const ; 42 int round double number const ; 43 double fraction
Trang 1Display 7.4 The const Parameter Modifier (part 2 of 3)
40 int dollarsPart( double amount) const ;
41 int centsPart( double amount) const ;
42 int round( double number) const ;
43 double fraction( double percent) const ;
44 //Converts a percentage to a fraction For example, fraction(50.3) returns 0.503.
45 };
46 //Returns true if the balance in account1 is greater than that
47 //in account2 Otherwise returns false.
48 bool isLarger( const BankAccount& account1, const BankAccount& account2);
49 void welcome( const BankAccount& yourAccount);
50 int main( )
51 {
52 BankAccount account1(6543.21, 4.5), account2;
53 welcome(account1);
54 cout << "Enter data for account 2:\n";
55 account2.input( );
56 if (isLarger(account1, account2))
57 cout << "account1 is larger.\n";
58 else
59 cout << "account2 is at least as large as account1.\n";
60 return 0;
61 }
62
63 bool isLarger( const BankAccount& account1, const BankAccount& account2)
64 {
65 return (account1.getBalance( ) > account2.getBalance( ));
66 }
67 void welcome( const BankAccount& yourAccount)
68 {
69 cout << "Welcome to our bank.\n"
70 << "The status of your account is:\n";
71 yourAccount.output( );
72 }
73 //Uses iostream and cstdlib:
74 void BankAccount::output( ) const
75 <The rest of the function definition is the same as in Display 7.2.>
76 <Other function definitions are the same as in Display 7.2, except that
77 const is added where needed to match the function declaration.>
Trang 2Self-Test Exercises
■ INLINE FUNCTIONS
You can give the complete definition of a member function within the definition of its
class Such definitions are called inline function definitions These inline definitions
are typically used for very short function definitions Display 7.5 shows the class in Display 7.4 rewritten with a number of inline functions
Inline functions are more than just a notational variant of the kind of member func-tion definifunc-tions we have already seen The compiler treats an inline funcfunc-tion in a special way The code for an inline function declaration is inserted at each location where the function is invoked This saves the overhead of a function invocation
All other things being equal, an inline function should be more efficient and hence presumably preferable to a function defined in the usual way However, all other things are seldom, if ever, equal Inline functions have the disadvantage of mixing the interface and implementation of a class and so go against the principle of encapsulation And, so the usual arguments go back and forth
It is generally believed that only very short function definitions should be defined inline For long function definitions, the inline version can actually be less efficient, because a large piece of code is repeated frequently Beyond that general rule, you will have to decide for yourself whether to use inline functions
Any function can be defined to be an inline function To define a nonmember func-tion to be inline, just place the keyword inline before the function declaration and function definition We will not use, or further discuss, inline nonmember functions in this book
7 Rewrite the definition of the class DayOfYear given in Display 7.3 so that the functions
getMonthNumber and getDay are defined inline
Display 7.4 The const Parameter Modifier (part 3 of 3)
S AMPLE D IALOGUE
Welcome to our bank.
The status of your account is:
Account balance: $6543.21
Rate: 4.5%
Enter data for account 2:
Enter account balance $100.00
Enter interest rate (NO percent sign): 10
account1 is larger.
inline function
Trang 3Display 7.5 Inline Function Definitions
1 #include <iostream>
2 #include <cmath>
3 #include <cstdlib>
4 using namespace std;
5 class BankAccount
6 {
7 public :
8 BankAccount( double balance, double rate);
9 BankAccount( int dollars, int cents, double rate);
10 BankAccount( int dollars, double rate);
12 void update( );
13 void input( );
14 void output( ) const ;
15 double getBalance( ) const { return (accountDollars + accountCents*0.01);}
16 int getDollars( ) const { return accountDollars; }
17 int getCents( ) const { return accountCents; }
18 double getRate( ) const { return rate; }
19 void setBalance( double balance);
20 void setBalance( int dollars, int cents);
21 void setRate( double newRate);
22 private :
23 int accountDollars; //of balance
24 int accountCents; //of balance
25 double rate; //as a percentage
26 int dollarsPart( double amount) const { return static_cast < int >(amount); }
27 int centsPart( double amount) const ;
28 int round( double number) const
29 { return static_cast < int >(floor(number + 0.5)); }
30 double fraction( double percent) const { return (percent/100.0); }
31 };
<Inline functions have no further definitions Other function definitions are as in Display 7.4.>
This is Display 7.4 rewritten using inline member functions
Trang 4■ STATIC MEMBERS
Sometimes you want to have one variable that is shared by all the objects of a class For example, you might want one variable to count the number of times a particular
mem-ber function is invoked by all objects of the class Such variables are called static
vari-ables and can be used for objects of the class to communicate with each other or
coordinate their actions Such variables allow some of the advantages of global variables without opening the flood gates to all the abuses that true global variables invite In particular, a static variable can be private so that only objects of the class can directly access it
If a function does not access the data of any object and yet you want the function to
be a member of the class, you can make it a static function Static functions can be invoked in the normal way, using a calling object of the class However, it is more com-mon and clearer to invoke a static function using the class name and scope resolution operator, as in the following example:
Server::getTurn( ) Because a static function does not need a calling object, the definition of a static function cannot use anything that depends on a calling object A static function defini-tion cannot use any nonstatic variables or nonstatic member funcdefini-tions, unless the non-static variable or function has a calling object that is a local variable or some object otherwise created in the definition If that last sentence seems hard to understand, just use the simpler rule that the definition of a static function cannot use anything that depends on a calling object
Display 7.6 is a demonstration program that uses both static variables and static functions Note that static variables are indicated by the qualifying keyword static at the start of their declaration Also notice that all the static variables are initialized as follows:
int Server::turn = 0;
int Server::lastServed = 0;
bool Server::nowOpen = true ; Such initialization requires a bit of explanation Every static variable must be initialized outside the class definition Also, a static variable cannot be initialized more than once
As in Display 7.6, private static variables—in fact, all static variables—are initialized outside the class This may seem to be contrary to the notion of private However, the author of a class is expected to do the initializations, typically in the same file as the class definition In that case, no programmer who uses the class can initialize the static variables, since a static variable cannot be initialized a second time
Notice that the keyword static is used in the member function declaration but is not used in the member function definition
static variable
initializing
static
member
variables
Trang 5Display 7.6 Static Members (part 1 of 2)
1 #include <iostream>
2 using namespace std;
3 class Server
4 {
5 public :
6 Server( char letterName);
7 static int getTurn( );
8 void serveOne( );
9 static bool stillOpen( );
10 private :
11 static int turn;
12 static int lastServed;
13 static bool nowOpen;
14 char name;
15 };
16 int Server:: turn = 0;
17 int Server:: lastServed = 0;
18 bool Server::nowOpen = true ;
19 int main( )
20 {
21 Server s1(’A’), s2(’B’);
22 int number, count;
23 do
25 cout << "How many in your group? ";
26 cin >> number;
27 cout << "Your turns are: ";
28 for (count = 0; count < number; count++)
29 cout << Server::getTurn( ) << ' ';
30 cout << endl;
31 s1.serveOne( );
32 s2.serveOne( );
33 } while (Server::stillOpen( ));
34 cout << "Now closing service.\n";
35 return 0;
36 }
37
38 Server::Server( char letterName) : name(letterName)
39 { /*Intentionally empty*/ }
40 int Server::getTurn( )
41 {
43 return turn;
44 }
Since getTurn is static, only static members can be referenced in here.
Trang 6The program in Display 7.6 is the outline of a scenario that has one queue of clients waiting for service and two servers to service this single queue You can come up with a number of system programming scenarios to flesh this out to a realistic example For a simple minded model just to learn the concepts, think of the numbers produced by getTurn as those little slips of paper handed out to customers in a delicatessen or ice cream shop The two servers are then two clerks who wait on customers One perhaps peculiar detail of this shop is that customers arrive in groups but are waited on one at a time (perhaps to order their own particular kind of sandwich or ice cream flavor)
Display 7.6 Static Members (part 2 of 2)
45 bool Server::stillOpen( )
46 {
47 return nowOpen;
48 }
49 void Server::serveOne( )
50 {
51 if (nowOpen && lastServed < turn)
54 cout << "Server " << name
55 << " now serving " << lastServed << endl;
57 if (lastServed >= turn) //Everyone served
58 nowOpen = false ;
59 }
S AMPLE D IALOGUE
How many in your group? 3
Your turns are: 1 2 3
Server A now serving 1
Server B now serving 2
How many in your group? 2
Your turns are: 4 5
Server A now serving 3
Server B now serving 4
How many in your group? 0
Your turns are:
Server A now serving 5
Now closing service.
Trang 7Self-Test Exercises
8 Could the function defined as follows be added to the class Server in Display 7.6 as a static function? Explain your answer
void Server::showStatus( ) {
cout << "Currently serving " << turn << endl;
cout << "server name " << name << endl;
}
■ NESTED AND LOCAL CLASS DEFINITIONS
The material in this section is included for reference value and, except for a brief pass-ing reference in Chapter 17, is not used elsewhere in this book
You can define a class within a class Such a class within a class is called a nested
class The general layout is obvious:
class OuterClass {
public : .
private : class InnerClass {
.
};
.
};
A nested class can be either public or private If it is private, as in our sample layout, then it cannot be used outside of the outer class Whether the nested class is public or private, it can be used in member function definitions of the outer class
Since the nested class is in the scope of the outer class, the name of the nested class, like InnerClass in our sample layout, may be used for something else outside of the outer class If the nested class is public, the nested class can be used as a type outside of the outer class However, outside of the outer class, the type name of the nested class is OuterClass::InnerClass
We will not have occasion to use such nested class definitions in this book However,
in Chapter 17 we do suggest one possible application for nested classes.2
A class definition can also be defined within a function definition In such cases the
class is called a local class, since its meaning is confined to the function definition A
2The suggestion is in the subsection of Chapter 17 entitled “Friend Classes and Similar Alter-natives.”
nested class
local class
Trang 8local class may not contain static members We will not have occasion to use local classes in this book
Vectors—A Preview of the Standard Template Library
“Well, I’ll eat it,” said Alice, “and if it makes me grow larger, I can reach the key; and if it makes me grow smaller, I can creep under the door; so either way I’ll get into the garden.”
Lewis Carroll, Alice’s Adventures in Wonderland
Vectors can be thought of as arrays that can grow (and shrink) in length while your
program is running In C++, once your program creates an array, it cannot change the length of the array Vectors serve the same purpose as arrays except that they can change length while the program is running
Vectors are formed from a template class in the Standard Template Library (STL)
We discuss templates in Chapter 16 and discuss the STL in Chapter 19 However, it is easy to learn some basic uses of vectors before you learn about templates and the STL
in detail You do not need to know a great deal about classes to use vectors You can cover this section on vectors after reading Chapter 6 You need not have read the previ-ous sections of this chapter before covering this section
■ VECTOR BASICS
Like an array, a vector has a base type, and like an array, a vector stores a collection of values of its base type However, the syntax for a vector type and a vector variable decla-ration is different from the syntax for arrays
You declare a variable, v, for a vector with base type int as follows:
vector< int > v;
The notation vector< Base_Type > is a template class, which means you can plug in any
type for Base_Type and that will produce a class for vectors with that base type You can simply think of this as specifying the base type for a vector in the same sense as you specify a base type for an array You can use any type, including class types, as the base type for a vector The notation vector<int> is a class name and so the previous declara-tion of v as a vector of type vector<int> includes a call to the default constructor for the class vector<int> that creates a vector object that is empty (has no elements) Vector elements are indexed starting with 0, the same as arrays The square brackets notation can be used to read or change these elements, just as with an array For exam-ple, the following changes the value of the ith element of the vector v and then outputs that changed value (i is an int variable.)
7.3
vector
declaring a
vector
variable
template class
v[i]
Trang 9v[i] = 42;
cout << "The answer is " << v[i];
There is, however, a restriction on this use of the square brackets notation with vectors that is unlike the same notation used with arrays You can use v[i] to change the value
of the ith element However, you cannot initialize the ith element using v[i]; you can only change an element that has already been given some value To add an element to a vector for the first time, you normally use the member function push_back
You add elements to a vector in order of positions, first at position 0, then position
1, then 2, and so forth The member function push_back adds an element in the next available position For example, the following gives initial values to elements 0, 1, and
2 of the vector sample: vector< double > sample;
sample.push_back(0.0);
sample.push_back(1.1);
sample.push_back(2.2);
The number of elements in a vector is called the size of the vector The member
function size can be used to determine how many elements are in a vector For exam-ple, after the previously shown code is executed, sample.size( ) returns 3 You can write out all the elements currently in the vector sample as follows:
for ( int i = 0; i < sample.size( ); i++) cout << sample[i] << endl;
The function size returns a value of type unsigned int, not a value of type int This returned value should be automatically converted to type int when it needs to be
of type int, but some compiler may warn you that you are using an unsigned int where an int is required If you want to be very safe, you can always apply a type cast to convert the returned unsigned int to an int, or in cases like this for loop, use a loop control variable of type unsigned int as follows:
for ( unsigned int i = 0; i < sample.size( ); i++) cout << sample[i] << endl;
A simple demonstration illustrating some basic vector techniques is given in Display 7.7
There is a vector constructor that takes one integer argument and will initialize the number of positions given as the argument For example, if you declare v as follows:
vector< int > v(10);
then the first ten elements are initialized to 0 and v.size( ) would return 10 You can then set the value of the ith element using v[i] for values of i equal to 0 through 9 In particular, the following could immediately follow the declaration:
for ( unsigned int i = 0; i < 10; i++) v[i] = i;
push_back
size
size unsigned int
Trang 10To set the ith element for i greater than or equal to 10, you would use push_back When you use the constructor with an integer argument, vectors of numbers are ini-tialized to the zero of the number type If the vector base type is a class type, the default constructor is used for initialization
Display 7.7 Using a Vector
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4 int main( )
5 {
6 vector< int > v;
7 cout << "Enter a list of positive numbers.\n"
8 << "Place a negative number at the end.\n";
9 int next;
10 cin >> next;
11 while (next > 0)
13 v.push_back(next);
14 cout << next << " added ";
15 cout << "v.size( ) = " << v.size( ) << endl;
16 cin >> next;
18 cout << "You entered:\n";
19 for ( unsigned int i = 0; i < v.size( ); i++)
20 cout << v[i] << " ";
21 cout << endl;
22 return 0;
23 }
S AMPLE D IALOGUE
Enter a list of positive numbers.
Place a negative number at the end.
2 4 6 8 -1
2 added v.size = 1
4 added v.size = 2
6 added v.size = 3
8 added v.size = 4
You entered:
2 4 6 8