The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Introduction to Programming with C++, 3rd Edition, By Y. Daniel Liang

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by pujzbekedjlbzuizpx, 2021-01-13 21:41:53

Introduction to Programming with C++, 3rd Edition, By Y. Daniel Liang

Introduction to Programming with C++, 3rd Edition, By Y. Daniel Liang

Programming Exercises 329

***8.8 (Shuffle rows) Write a function that shuffles the rows in a two-dimensional int

array using the following header:

void shuffle(int m[][2], int rowSize);

Write a test program that shuffles the following matrix:

int m[][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}};

**8.9 (Algebra: multiply two matrices) Write a function to multiply two matrices a and

b and save the result in c.

a11 a12 a13 b11 b12 b13 c11 c12 c13

£ a21 a22 a23 ≥ * £ b21 b22 b23 ≥ = £ c21 c22 c23 ≥

a31 a32 a33 b31 b32 b33 c31 c32 c33

The header of the function is

const int N = 3;
void multiplyMatrix(const double a[][N],

const double b[][N], double c[][N]);

Each element cij is ai1 * b1j + ai2 * b2j + ai3 * b3j.
Write a test program that prompts the user to enter two 3 * 3 matrices and dis-
plays their product. Here is a sample run:

Enter matrix1: 1 2 3 4 5 6 7 8 9

Enter matrix2: 0 2 4 1 4.5 2.2 1.1 4.3 5.2

The multiplication of the matrices is

123 0 2.0 4.0 5.3 23.9 24

4 5 6 * 1 4.5 2.2 = 11.6 56.3 58.2

789 1.1 4.3 5.2 17.9 88.7 92.4

Section 8.6

**8.10 (All closest pairs) Listing 8.3, FindNearestPoints.cpp, finds one closest pair.

Revise the program to display all closest pairs with the same minimum distance.
Here is a sample run:

Enter the number of points: 8
Enter 8 points: 0 0 1 1 -1 -1 2 2 -2 -2 -3 -3 -4 -4 5 5
The closest two points are (0.0, 0.0) and (1.0, 1.0)
The closest two points are (0.0, 0.0) and (-1.0, -1.0)
The closest two points are (1.0, 1.0) and (2.0, 2.0)
The closest two points are (-1.0, -1.0) and (-2.0, -2.0)
The closest two points are (-2.0, -2.0) and (-3.0, -3.0)
The closest two points are (-3.0, -3.0) and (-4.0, -4.0)
Their distance is 1.4142135623730951

**8.11 (Game: nine heads and tails) Nine coins are placed in a 3 * 3 matrix with some

face up and some face down. You can represent the state of the coins using a 3 * 3
matrix with values 0 (head) and 1 (tail). Here are some examples:

000 101 110 101 100
010 001 100 110 111
000 100 001 100 110

330 Chapter 8 Multidimensional Arrays

Each state can also be represented using a binary number. For example, the pre-
ceding matrices correspond to the numbers

000010000 101001100 110100001 101110100 100111110

The total number of possibilities is 512. So you can use decimal numbers 0, 1, 2,
3, . . . , and 511 to represent all states of the matrix. Write a program that prompts
the user to enter a number between 0 and 511 and displays the corresponding
matrix with characters H and T. Here is a sample run:

Enter a number between 0 and 511: 7
HHH
HHH
TTT

*8.12 The user entered 7, which corresponds to 000000111. Since 0 stands for H and 1
for T, the output is correct.
VideoNote
(Points nearest to each other) Listing 8.3, FindNearestPoints.cpp, is a program
3-D nearest points that finds two points in a two-dimensional space nearest to other. Revise the pro-
gram so that it finds two points in a three-dimensional space nearest to other. Use
a two-dimensional array to represent the points. Test the program using the follow-
ing points:

double points[][3] = {{-1, 0, 3}, {-1, -1, -1}, {4, 1, 1},
{2, 0.5, 9}, {3.5, 2, -1}, {3, 1.5, 3}, {-1.5, 4, 2},
{5.5, 4, -0.5}};

*8.13 The formula for computing the distance between two points (x1, y1, z1) and
(x2, y2, z2) is 2(x2 - x1)2 + (y2 - y1)2 + (z2 - z1)2.

(Sort two-dimensional array) Write a function to sort a two-dimensional array
using following header:

void sort(int m[][2], int numberOfRows)

*8.14 The function performs a sort primarily on the first element in the rows and then
secondarily on the second element in the rows if the first elements are equal. For
example, the array {{4, 2}, {1, 7}, {4, 5}, {1, 2}, {1, 1}, {4, 1}} will be sorted to
{{1, 1}, {1, 2}, {1, 7}, {4, 1}, {4, 2}, {4, 5}}. Write a test program that prompts
the user to enter 10 points, invokes this function, and displays the sorted points.

(Largest row and column) Write a program that randomly fills in 0s and 1s into a
4 * 4 matrix, prints the matrix, and finds the first row and first column with the
most 1s. Here is a sample run of the program:

0011
1011
1101
1010
The largest row index: 1
The largest column index: 2

Programming Exercises 331

*8.15 (Algebra: 2 * 2 matrix inverse) The inverse of a square matrix A is denoted A-1,
such that A × A-1 = I, where I is the identity matrix with all 1s on the diagonal and

0 on all other cells. For example, the inverse of matrix J1 2 R is, J -2 - 1 R ,
3 4 1.5 0.5

i.e.,

J1 2R * J -2 - 1 R = J1 0R
3 4 1.5 0.5 0 1

The inverse of a 2 * 2 matrix A can be obtained using the following formula if
ad – bc != 0:

ab A-1 = ad 1 d -bR
A=J R - bc J -c a

cd

Implement the following function to obtain an inverse of the matrix:

void inverse(const double A[][2], double inverseOfA[][2])

Write a test program that prompts the user to enter a, b, c, d for a matrix, and
displays its inverse matrix. Here is a sample run:

Enter a, b, c, d: 1 2 3 4
-2.0 1.0
1.5 -0.5

Enter a, b, c, d: 0.5 2 1.5 4.5
-6.0 2.6666666666666665
2.0 -0.6666666666666666

*8.16 (Geometry: same line?) Programming Exercise 6.20 gives a function for testing

whether three points are on the same line. Write the following function to test
whether all the points in points array are on the same line.

const int SIZE = 2;
bool sameLine(const double points[][SIZE], int numberOfPoints)

Write a program that prompts the user to enter five points and displays whether
they are on the same line. Here are sample runs:

Enter five points: 3.4 2 6.5 9.5 2.3 2.3 5.5 5 -5 4
The five points are not on same line

Enter five points: 1 1 2 2 3 3 4 4 5 5
The five points are on same line

332 Chapter 8 Multidimensional Arrays

Sections 8.7–8.8
***8.17 (Locate the largest element) Write the following function that finds the location

of the largest element in a two-dimensional array.

void locateLargest(const double a[][4], int location[])

The location is stored in a one-dimensional array location that contains two
elements. These two elements indicate the row and column indices of the largest
element in the two-dimensional array. Write a test program that prompts the user
to enter a 3 * 4 two-dimensional array and displays the location of the largest
element in the array. Here is a sample run:

Enter the array:
23.5 35 2 10
4.5 3 45 3.5
35 44 5.5 9.6
The location of the largest element is at (1, 2)

*8.18 (Algebra: 3 * 3 matrix inverse) The inverse of a square matrix A is denoted A-1,
such that A × A-1 = I, where I is the identity matrix with all 1s on the diagonal

121

and 0 on all other cells. For example, the inverse of matrix C 2 3 1 S is

-2 0.5 0.5 453

C 1 0.5 -0.5 S , i.e.,

1 -1.5 0.5

121 -2 0.5 0.5 100

C 2 3 1 S * C 1 0.5 -0.5 S = C 0 1 0 S

453 1 -1.5 0.5 001

a11 a12 a13
The inverse of a 3 * 3 matrix A = C a21 a22 a23 S can be obtained using the

a31 a32 a33

following formula if ͉ A͉ ϶ 0:

A-1 = 1 a22a33 - a23a32 a13a32 - a12a33 a12a23 - a13a22
͉A͉ C a23a31 - a21a33 a11a33 - a13a31 a13a21 - a11a23 S
- a22a31 a12a31 - a11a32 a11a22 - a12a21
a21a32

a11 a12 a13
͉ A ͉ = 3 a21 a22 a23 3 = a11a22a33 + a31a12a23 + a13a21a32

a31 a32 a33
- a13a22a31 - a11a23a32 - a33a21a12.

Implement the following function to obtain an inverse of the matrix:

void inverse(const double A[][3], double inverseOfA[][3])

Programming Exercises 333

Write a test program that prompts the user to enter a11, a12, a13, a21, a21,
a23, a31, a32, a33, for a matrix, and displays its inverse matrix. Here is a sample run:

Enter a11, a12, a13, a21, a22, a23, a31, a32, a33: 1 2 1 2 3 1 4 5 3
-2 0.5 0.5
1 0.5 -0.5
1 -1.5 0.5

Enter a11, a12, a13, a21, a22, a23, a31, a32, a33: 1 4 2 2 5 8 2 1 8
2.0 -1.875 1.375
0.0 0.25 -0.25
-0.5 0.4375 -0.1875

***8.19 (Financial tsunami) Banks loan money to each other. In tough economic times, if
a bank goes bankrupt, it may not be able to pay back the loan. A bank’s total asset
is its current balance plus its loans to other banks. Figure 8.7 is a diagram that
shows five banks. The banks’ current balances are 25, 125, 175, 75, and 181
million dollars, respectively. The directed edge from node 1 to node 2 indicates
that bank 1 loans 40 million dollars to bank 2.

25 100.5 125 85
0 1

320.5 125 40 75
125 3

75

125 2 175

181 4

FIGURE 8.7 Banks loan money to each other.

If a bank’s total asset is under a certain limit, the bank is unsafe. If a bank is
unsafe, the money it borrowed cannot be returned to the lender, and the lender
cannot count the loan in its total asset. Consequently, the lender may also be
unsafe, if its total asset is under the limit. Write a program to find all unsafe
banks. Your program reads the input as follows. It first reads two integers n and
limit, where n indicates the number of banks and limit is the minimum asset
for keeping a bank safe. It then reads n lines that describe the information for n
banks with id from 0 to n-1. The first number in the line is the bank’s balance,
the second number indicates the number of banks that borrowed money from the
bank, and the rest are pairs of two numbers. Each pair describes a borrower. The
first number in the pair is the borrower’s id and the second is the amount bor-
rowed. Assume that the maximum number of the banks is 100. For example, the
input for the five banks in Figure 8.7 is as follows (the limit is 201):

5 201
25 2 1 100.5 4 320.5
125 2 2 40 3 85
175 2 0 125 3 75
75 1 0 125
181 1 2 125

334 Chapter 8 Multidimensional Arrays

The total asset of bank 3 is (75 + 125), which is under 201. So bank 3 is unsafe.
After bank 3 becomes unsafe, the total asset of bank 1 becomes 125 + 40. So
bank 1 is also unsafe. The output of the program should be

Unsafe banks are 3 1

***8.20 (Hint: Use a two-dimensional array borrowers to represent loans. loan[i]
[j] indicates the loan that bank i loans to bank j. Once bank j becomes unsafe,
loan[i][j] should be set to 0.)

(TicTacToe game) In a game of TicTacToe, two players take turns marking an
available cell in a 3 * 3 grid with their respective tokens (either X or O). When
one player has placed three tokens in a horizontal, vertical, or diagonal row on the
grid, the game is over and that player has won. A draw (no winner) occurs when all
the cells on the grid have been filled with tokens and neither player has achieved
a win. Create a program for playing TicTacToe. The program prompts the first
player to enter an X token, and then prompts the second player to enter an O token.
Whenever a token is entered, the program redisplays the board on the console and
determines the status of the game (win, draw, or unfinished). Here is a sample run:

-------------
||||
-------------
||||
-------------
||||
-------------
Enter a row (0, 1, or 2) for player X: 1
Enter a column (0, 1, or 2) for player X: 1

-------------
||||
-------------
| |X| |
-------------
||||
-------------
Enter a row (0, 1, or 2) for player O: 1
Enter a column (0, 1, or 2) for player O: 2

-------------
||||
-------------
| |X|O|
-------------
||||
-------------
Enter a row (0, 1, or 2) for player X:

...

-------------
|X| | |
-------------
|O|X|O|
-------------
| | |X|
-------------
X player won

Programming Exercises 335

**8.21 (Pattern recognition: consecutive four equal numbers) Write the following func-

tion that tests whether a two-dimensional array has four consecutive numbers of
the same value, either horizontally, vertically, or diagonally.

bool isConsecutiveFour(int values[][7])

Write a test program that prompts the user to enter the number of rows and col-
umns of a two-dimensional array and then the values in the array and displays
true if the array contains four consecutive numbers with the same value. Other-
wise, display false. Here are some examples of the true cases:

0103161 0103161 0103161 0103161
0168601 0168601 0168601 0168601
5621829 5521829 5621629 9621829
6561191 6561191 6566191 6961191
1361407 1561407 1361407 1391407
3333407 3533407 3633407 3339407

***8.22 (Game: connect four) Connect four is a two-player board game in which the

players alternately drop colored disks into a seven-column, six-row vertically-
suspended grid, as shown below.

The objective of the game is to connect four same-colored disks in a row,
a column, or a diagonal before your opponent can do likewise. The program
prompts two players to drop a RED (shown in dark blue) or YELLOW (shown in
light blue) disk alternately. Whenever a disk is dropped, the program redisplays
the board on the console and determines the status of the game (win, draw, or
continue). Here is a sample run:

||||||||
||||||||
||||||||
||||||||
||||||||
||||||||
----------------------
Drop a red disk at column (0–6): 0

336 Chapter 8 Multidimensional Arrays

||||||||
||||||||
||||||||
||||||||
||||||||
|R| | | | | | |
----------------------
Drop a yellow disk at column (0–6): 3

||||||||
||||||||
||||||||
||||||||
||||||||
|R| | |Y| | | |

...
...
...

Drop a yellow disk at column (0–6): 6
||||||||
||||||||
| | | |R| | | |
| | | |Y|R|Y| |
| | |R|Y|Y|Y|Y|
|R|Y|R|Y|R|R|R|
----------------------
The yellow player won

*8.23 (Central city) Given a set of cities, the central point is the city that has the short-
est total distance to all other cities. Write a program that prompts the user to enter
the number of cities and the locations of the cities (coordinates), and finds the
central city and its total distance to all other cities. Assume that the maximum
number of cities is 20.

Enter the number of cities: 5
Enter the coordinates of the cities: 2.5 5 5.1 3 1 9 5.4 54 5.5 2.1
The central city is at (2.5, 5.0)
The total distance to all other cities is 60.81

*8.24 (Checking Sudoku solution) Listing 8.4 checks whether a solution is valid by check-
*8.25 ing whether every number is valid in the board. Rewrite the program by checking
whether every row, every column and every small box has numbers 1 to 9.

(Markov matrix) An n * n matrix is called a positive Markov matrix, if each
element is positive and the sum of the elements in each column is 1. Write the
following function to check whether a matrix is a Markov matrix:

const int SIZE = 3;
bool isMarkovMatrix(const double m[][SIZE]);

Programming Exercises 337

Write a test program that prompts the user to enter a 3 * 3 matrix of double
values and tests whether it is a Markov matrix. Here are sample runs:

Enter a 3 by 3 matrix row by row:
0.15 0.875 0.375
0.55 0.005 0.225
0.30 0.12 0.4
It is a Markov matrix

Enter a 3 by 3 matrix row by row:
0.95 -0.875 0.375
0.65 0.005 0.225
0.30 0.22 -0.4
It is not a Markov matrix

*8.26 (Row sorting) Implement the following function to sort the rows in a two-

dimensional array. A new array is returned. The original array is intact.

const int SIZE = 3;
void sortRows(const double m[][SIZE], double result[][SIZE]);

Write a test program that prompts the user to enter a 3 * 3 matrix of double
values and display a new row-sorted matrix. Here is a sample run:

Enter a 3 by 3 matrix row by row:
0.15 0.875 0.375
0.55 0.005 0.225
0.30 0.12 0.4
The row-sorted array is
0.15 0.375 0.875
0.005 0.225 0.55
0.12 0.30 0.4

*8.27 (Column sorting) Implement the following function to sort the columns in a two-

dimensional array. A new array is returned. The original array is intact.

const int SIZE = 3;
void sortColumns(const double m[][SIZE], double result[][SIZE]);

Write a test program that prompts the user to enter a 3 * 3 matrix of double
values and display a new column-sorted matrix. Here is a sample run:

Enter a 3 by 3 matrix row by row:
0.15 0.875 0.375
0.55 0.005 0.225
0.30 0.12 0.4
The column-sorted array is
0.15 0.0050 0.225
0.3 0.12 0.375
0.55 0.875 0.4

338 Chapter 8 Multidimensional Arrays

8.28 (Strictly identical arrays) Two two-dimensional arrays m1 and m2 are strictly

identical if their corresponding elements are equal. Write a function that returns
true if m1 and m2 are strictly identical, using the following header:

const int SIZE = 3;
bool equals(const int m1[][SIZE], const int m2[][SIZE]);

Write a test program that prompts the user to enter two 3 * 3 arrays of integers
and displays whether the two are strictly identical. Here are the sample runs.

Enter m1: 51 22 25 6 1 4 24 54 6
Enter m2: 51 22 25 6 1 4 24 54 6
Two arrays are strictly identical

Enter m1: 51 25 22 6 1 4 24 54 6
Enter m2: 51 22 25 6 1 4 24 54 6
Two arrays are not strictly identical

8.29 (Identical arrays) Two two-dimensional arrays m1 and m2 are identical if they

have the same contents. Write a function that returns true if m1 and m2 are iden-
tical, using the following header:

const int SIZE = 3;
bool equals(const int m1[][SIZE], const int m2[][SIZE]);

Write a test program that prompts the user to enter two 3 * 3 arrays of integers
and displays whether the two are identical. Here are the sample runs.

Enter m1: 51 25 22 6 1 4 24 54 6
Enter m2: 51 22 25 6 1 4 24 54 6
Two arrays are identical

Enter m1: 51 5 22 6 1 4 24 54 6
Enter m2: 51 22 25 6 1 4 24 54 6
Two arrays are not identical

*8.30 (Algebra: solve linear equations) Write a function that solves the following

2 * 2 system of linear equation:

a00x + a01y = b0 x = b0a11 - b1a01 y = b1a00 - b0a10
a10x + a11y = b1 a00a11 - a01a10 a00a11 - a01a10

The function header is

const int SIZE = 2;
bool linearEquation(const double a[][SIZE], const double b[],

double result[]);

The function returns false if a00a11 - a01a10 is 0; otherwise, returns true.
Write a test program that prompts the user to enter a00, a01, a10, a11, b0, b1, and
display the result. If a00a11 - a01a10 is 0, report that "The equation has no
solution". A sample run is similar to Programming Exercise 3.3.

Programming Exercises 339

*8.31 (Geometry: intersecting point) Write a function that returns the intersecting point
of the two lines. The intersecting point of the two lines can be found by using
the formula shown in Programming Exercise 3.22. Assume that (x1, y1) and
(x2, y2) are the two points in line 1 and (x3, y3) and (x4, y4) on line 2. If the
equation has no solutions, the two lines are parallel. The function header is

const int SIZE = 2;
bool getIntersectingPoint(const double points[][SIZE],

double result[]);

*8.32 The points are stored in a 4 * 2 two-dimensional array points with (points[0]
[0], points[0][1]) for (x1, y1). The function returns the intersecting point
and true, if the two lines are parallel. Write a program that prompts the user to
enter four points and display the intersecting point. See Programming Exercise
3.22 for a sample run.

(Geometry: area of a triangle) Write a function that returns the area of a triangle
using the following header:

const int SIZE = 2;
double getTriangleArea(const double points[][SIZE]);

The points are stored in a 3 * 2 two-dimensional array points with (points[0]
[0], points[0][1]) for (x1, y1). The triangle area can be computed using the
formula in Programming Exercise 2.19. The function returns 0, if the three points
are on the same line. Write a program that prompts the user to enter two lines and
display the intersecting point. Here is a sample run of the program:

Enter x1, y1, x2, y2, x3, y3: 2.5 2 5 -1.0 4.0 2.0
The area of the triangle is 2.25

Enter x1, y1, x2, y2, x3, y3: 2 2 4.5 4.5 6 6
The three points are on the same line

*8.33 (Geometry: polygon subareas) A convex 4-vertex polygon is divided into four

triangles, as shown in Figure 8.8.

v2 (x2, y2)

v1 (x1, y1) v3 (x3, y3)

v4 (x4, y4)

FIGURE 8.8 A 4-vertex polygon is defined by four vertices.

Write a program that prompts the user to enter the coordinates of the four ver-
tices and displays the areas of the four triangles in increasing order. Here is a
sample run:

Enter x1, y1, x2, y2, x3, y3, x4, y4: -2.5 2 4 4 3 -2 -2 -3.5
The areas are 1.390 1.517 8.082 8.333

340 Chapter 8 Multidimensional Arrays

*8.34 (Geometry: rightmost lowest point) In computational geometry, often you need

to find the rightmost lowest point in a set of points. Write the following function
that returns the rightmost lowest point in a set of points.

const int SIZE = 2;
void getRightmostLowestPoint(const double points[][SIZE],

int numberOfPoints, double rightMostPoint[]);

Write a test program that prompts the user to enter the coordinates of six points
and displays the rightmost lowest point. Here is a sample run:

Enter 6 points: 1.5 2.5 -3 4.5 5.6 -7 6.5 -7 8 1 10 2.5
The rightmost lowest point is (6.5, -7.0)

*8.35 (Game: find the flipped cell) Suppose you are given a 6 * 6 matrix filled with 0
and 1. All rows and all columns have the even number of 1s. Let the user flip one
cell (i.e., flip from 1 to 0 or from 0 to 1) and write a program to find which cell
was flipped. Your program should prompt the user to enter a 6 * 6 array with 0
and 1 and find the first row r and first column c where the parity is violated (i.e.,
the number of 1’s is not even). The flipped cell is at (r, c). Here is a sample run:

Enter a 6-by-6 matrix row by row:
111011
111100
010111
111111
011110
100001
The first row and column where the parity is violated is at (0, 1)

*8.36 (Parity checking) Write a program that generates a 6 * 6 two-dimensional

matrix filled with 0 and 1, displays the matrix, and checks if every row and every
column have the even number of 1s.

CHAPTER

9

OBJECTS AND CLASSES

Objectives

■ To describe objects and classes, and to use classes to model objects
(§9.2).

■ To use UML graphical notations to describe classes and objects (§9.2).

■ To demonstrate defining classes and creating objects (§9.3).

■ To create objects using constructors (§9.4).

■ To access data fields and invoke functions using the object member
access operator (.) (§9.5).

■ To separate a class definition from a class implementation (§9.6).

■ To prevent multiple inclusions of header files using the #ifndef
inclusion guard directive (§9.7).

■ To know what inline functions in a class are (§9.8).

■ To declare private data fields with appropriate get and set functions
for data field encapsulation and make classes easy to maintain (§9.9).

■ To understand the scope of data fields (§9.10).

■ To apply class abstraction to develop software (§9.11).

342 Chapter 9 Objects and Classes

why OOP? 9.1 Introduction

Object-oriented programming enables you to develop large-scale software effectively.

Key

Point Having learned the material in earlier chapters, you are able to solve many programming
problems using selections, loops, functions, and arrays. However, these features are not suf-
ficient for developing large-scale software systems. This chapter begins the introduction of
object-oriented programming, which will enable you to develop large-scale software systems
effectively.

9.2 Defining Classes for Objects

Key A class defines the properties and behaviors for objects.
Point
Object-oriented programming (OOP) involves programming using objects. An object rep-
object-oriented programming resents an entity in the real world that can be distinctly identified. For example, a student, a
object desk, a circle, a button, and even a loan can all be viewed as objects. An object has a unique
identity, state, and behavior.

state ■ The state of an object (also known as properties or attributes) is represented by
property data fields with their current values. A circle object, for example, has a data field,
data field radius, which is the property that characterizes a circle. A rectangle object, for
example, has data fields, width and height, which are the properties that character-
ize a rectangle.

behavior ■ The behavior of an object (also known as actions) is defined by functions. To invoke
a function on an object is to ask the object to perform an action. For example, you
may define a function named getArea() for circle objects. A circle object may
invoke getArea() to return its area.

class Objects of the same type are defined using a common class. A class is a template, blueprint,
contract or contract that defines what an object’s data fields and functions will be. An object is an
instance of a class. You can create many instances of a class. Creating an instance is referred
instantiation to as instantiation. The terms object and instance are often interchangeable. The relationship
object between classes and objects is analogous to the relationship between apple pie recipes and
instance apple pies. You can make as many apple pies as you want from a single recipe. Figure 9.1
shows a class named Circle and its three objects.

Class Name: Circle A class template

Data Fields:
radius is

Functions:
getArea

Circle Object 1 Circle Object 2 Circle Object 3 Three objects of
the Circle class
Data Fields: Data Fields: Data Fields:
radius is 1.0 radius is 25 radius is 125

FIGURE 9.1 A class is a blueprint for creating objects.

class A C++ class uses variables to define data fields and functions to define behaviors. Addi-
data field tionally, a class provides functions of a special type, known as constructors, which are invoked
function when a new object is created. A constructor is a special kind of function. Constructors can

9.2 Defining Classes for Objects 343

perform any action, but they are designed to perform initializing actions, such as initializing constructor
the data fields of objects. Figure 9.2 shows an example of the class for Circle objects.

class Circle Data field
{ Constructors
public: Function

// The radius of this circle
double radius;

// Construct a circle object
Circle()
{

radius = 1;
}

// Construct a circle object
Circle(double newRadius)
{

radius = newRadius;
}

// Return the area of this circle
double getArea()
{

return radius * radius * 3.14159;
}
};

FIGURE 9.2 A class is a blueprint that defines objects of the same type.

The illustration of class and objects in Figure 9.1 can be standardized using UML (Unified
Modeling Language) notation, as shown in Figure 9.3. This is called a UML class diagram, or UML class diagram
simply class diagram. The data field is denoted as

dataFieldName: dataFieldType

The constructor is denoted as

ClassName(parameterName: parameterType)

The function is denoted as

functionName(parameterName: parameterType): returnType

UML Class Diagram Circle Class name
The + symbol means public
+radius: double Data fields
Constructors and
+Circle() functions
+Circle(newRadius: double)
+getArea(): double

circle1: Circle circle2: Circle circle3: Circle UML notation
radius ϭ 1.0 radius ϭ 25 radius ϭ 125 for objects

FIGURE 9.3 Classes and objects can be represented using UML notations.

344 Chapter 9 Objects and Classes

9.3 Example: Defining Classes and Creating Objects

Classes are definitions for objects and objects are created from classes.

Key

Point Listing 9.1 is a program that demonstrates classes and objects. It constructs three circle objects
with radius 1.0, 25, and 125 and displays the radius and area of each. Change the radius of
the second object to 100 and display its new radius and area.

VideoNote LISTING 9.1 TestCircle.cpp

Use classes 1 #include <iostream>
define class 2 using namespace std;
3
data field 4 class Circle
no-arg constructor 5{
6 public:
second constructor 7 // The radius of this circle
8 double radius;
function 9
10 // Construct a default circle object
don’t omit 11 Circle()
main function 12 {
creating object 13 radius = 1;
creating object 14 }
creating object 15
accessing radius 16 // Construct a circle object
invoking getArea 17 Circle(double newRadius)
18 {
modify radius 19 radius = newRadius;
20 }
21
22 // Return the area of this circle
23 double getArea()
24 {
25 return radius * radius * 3.14159;
26 }
27 }; // Must place a semicolon here
28
29 int main()
30 {
31 Circle circle1(1.0);
32 Circle circle2(25);
33 Circle circle3(125);
34
35 cout << "The area of the circle of radius "
36 << circle1.radius << " is " << circle1.getArea() << endl;
37 cout << "The area of the circle of radius "
38 << circle2.radius << " is " << circle2.getArea() << endl;
39 cout << "The area of the circle of radius "
40 << circle3.radius << " is " << circle3.getArea() << endl;
41
42 // Modify circle radius
43 circle2.radius = 100;
44 cout << "The area of the circle of radius "
45 << circle2.radius << " is " << circle2.getArea() << endl;
46
47 return 0;
48 }

9.3 Example: Defining Classes and Creating Objects 345

The area of the circle of radius 1 is 3.14159
The area of the circle of radius 25 is 1963.49
The area of the circle of radius 125 is 49087.3
The area of the circle of radius 100 is 31415.9

The class is defined in lines 4–27. Don’t forget that the semicolon (;) in line 27 is required. ending class definition
The public keyword in line 6 denotes that all data fields, constructors, and functions can public
be accessed from the objects of the class. If you don’t use the public keyword, the visibility
is private by default. Private visibility will be introduced in Section 9.8. private by default
The main function creates three objects named circle1, circle2, and circle3 with radius
1.0, 25, and 125, respectively (lines 31–33). These objects have different radii but the same
functions. Therefore, you can compute their respective areas by using the getArea() function.
The data fields can be accessed via the object using circle1.radius, circle2.radius,
and circle3.radius, respectively. The functions are invoked using circle1.getArea(),
circle2.getArea(), and circle3.getArea(), respectively.
These three objects are independent. The radius of circle2 is changed to 100 in line 43.
The object’s new radius and area are displayed in lines 44–45.
As another example, consider TV sets. Each TV is an object with state (current channel,
current volume level, power on or off) and behaviors (change channels, adjust volume, turn
on/off). You can use a class to model TV sets. The UML diagram for the class is shown in
Figure 9.4.

TV The current channel (1 to 120) of this TV.
The current volume level (1 to 7) of this TV.
channel: int Indicates whether this TV is on/off.
volumeLevel: int
on: boolean Constructs a default TV object.
Turns on this TV.
+TV() Turns off this TV.
+turnOn(): void Sets a new channel for this TV.
+turnOff(): void Sets a new volume level for this TV.
+setChannel(newChannel: int): void Increases the channel number by 1.
+setVolume(newVolumeLevel: int): void Decreases the channel number by 1.
+channelUp(): void Increases the volume level by 1.
+channelDown(): void Decreases the volume level by 1.
+volumeUp(): void
+volumeDown(): void

FIGURE 9.4 The TV class models TV sets.

Listing 9.2 gives a program that defines the TV class and uses the TV class to create two
objects.

LISTING 9.2 TV.cpp define a class

1 #include <iostream>
2 using namespace std;
3
4 class TV
5{
6 public:

346 Chapter 9 Objects and Classes

data fields 7 int channel;
constructor 8 int volumeLevel; // Default volume level is 1
9 bool on; // By default TV is off
turn on TV 10
turn off TV 11 TV()
set a new channel 12 {
13 channel = 1; // Default channel is 1
set a new volume 14 volumeLevel = 1; // Default volume level is 1
increase channel 15 on = false; // By default TV is off
decrease channel 16 }
increase volume 17
decrease volume 18 void turnOn()
19 {
main function 20 on = true;
21 }
22
23 void turnOff()
24 {
25 on = false;
26 }
27
28 void setChannel(int newChannel)
29 {
30 if (on && newChannel >= 1 && newChannel <= 120)
31 channel = newChannel;
32 }
33
34 void setVolume(int newVolumeLevel)
35 {
36 if (on && newVolumeLevel >= 1 && newVolumeLevel <= 7)
37 volumeLevel = newVolumeLevel;
38 }
39
40 void channelUp()
41 {
42 if (on && channel < 120)
43 channel++;
44 }
45
46 void channelDown()
47 {
48 if (on && channel > 1)
49 channel--;
50 }
51
52 void volumeUp()
53 {
54 if (on && volumeLevel < 7)
55 volumeLevel++;
56 }
57
58 void volumeDown()
59 {
60 if (on && volumeLevel > 1)
61 volumeLevel--;
62 }
63 };
64
65 int main()
66 {

67 TV tv1; 9.4 Constructors 347
68 tv1.turnOn();
69 tv1.setChannel(30); create a TV
70 tv1.setVolume(3); turn on
71 set a new channel
72 TV tv2; set a new volume
73 tv2.turnOn();
74 tv2.channelUp(); create a TV
75 tv2.channelUp(); turn on
76 tv2.volumeUp(); increase channel
77
78 cout << "tv1's channel is " << tv1.channel increase volume
79 << " and volume level is " << tv1.volumeLevel << endl;
80 cout << "tv2's channel is " << tv2.channel display state
81 << " and volume level is " << tv2.volumeLevel << endl;
82
83 return 0;
84 }

tv1's channel is 30 and volume level is 3
tv2's channel is 3 and volume level is 2

Note that the channel and volume level are not changed if the TV is not on. Before changing a
channel or volume level, the current values are checked to ensure that the channel and volume
level are within the correct range.

The program creates two objects in lines 67 and 72, and invokes the functions on the
objects to perform actions for setting channels and volume levels and for increasing channels
and volumes. The program displays the state of the objects in lines 78–81. The functions are
invoked using a syntax such as tv1.turnOn() (line 68). The data fields are accessed using
a syntax such as tv1.channel (line 78).

These examples have given you a glimpse of classes and objects. You may have many
questions about constructors and objects, accessing data fields and invoking objects’ func-
tions. The sections that follow discuss these issues in detail.

9.4 Constructors Key
Point
A constructor is invoked to create an object.

Constructors are a special kind of function, with three peculiarities:

■ Constructors must have the same name as the class itself. constructor’s name

■ Constructors do not have a return type—not even void. no return type

■ Constructors are invoked when an object is created. Constructors play the role of invoke constructor
initializing objects.

The constructor has exactly the same name as the defining class. Like regular functions, constructor overloading
constructors can be overloaded (i.e., multiple constructors with the same name but different no void
signatures), making it easy to construct objects with different sets of data values.

It is a common mistake to put the void keyword in front of a constructor. For example,

void Circle()
{
}

348 Chapter 9 Objects and Classes

initialize data field Most C++ compilers will report an error, but some will treat this as a regular function, not
as a constructor.
no-arg constructor
default constructor Constructors are for initializing data fields. The data field radius does not have an initial
constructor initializer list value, so it must be initialized in the constructor (lines 13 and 19 in Listing 9.1). Note that a
variable (local or global) can be declared and initialized in one statement, but as a class mem-
ber, a data field cannot be initialized when it is declared. For example, it would be wrong to
replace line 8 in Listing 9.1 by

double radius = 5; // Wrong for data field declaration

A class normally provides a constructor without arguments (e.g., Circle()). Such con-
structor is called a no-arg or no-argument constructor.

A class may be defined without constructors. In this case, a no-arg constructor with an
empty body is implicitly defined in the class. Called a default constructor, it is provided auto-
matically only if no constructors are explicitly defined in the class.

Data fields may be initialized in the constructor using an initializer list in the following
syntax:

ClassName(parameterList)
: datafield1(value1), datafield2(value2) // Initializer list

{
// Additional statements if needed

}

The initializer list initializes datafield1 with value1 and datafield2 with value2.
For example,

Circle::Circle() same as Circle::Circle()
: radius(1) {

{ radius = 1;
} }

(a) (b)

Constructor in (b), which does not use an initializer list, is actually more intuitive than the
one in (a). However, using an initializer list is necessary to initialize object data fields that
don’t have a no-arg constructor. This is an advanced topic covered in Supplement IV.E on the
Companion Website.

9.5 Constructing and Using Objects

Key An object’s data and functions can be accessed through the dot (.) operator via the
Point
object’s name.

construct objects A constructor is invoked when an object is created. The syntax to create an object using the
no-arg constructor is

invoke no-arg constructor ClassName objectName;

For example, the following declaration creates an object named circle1 by invoking the
Circle class’s no-arg constructor.

Circle circle1;

construct with args The syntax to create an object using a constructor with arguments is

ClassName objectName(arguments);

9.5 Constructing and Using Objects 349

For example, the following declaration creates an object named circle2 by invoking the
Circle class’s constructor with a specified radius 5.5.

Circle circle2(5.5);

In OOP term, an object’s member refers to its data fields and functions. Newly created
objects are allocated in the memory. After an object is created, its data can be accessed and its dot operator
functions invoked using the dot operator (.), also known as the object member access operator: member access operator

■ objectName.dataField references a data field in the object.

■ objectName.function(arguments) invokes a function on the object.

For example, circle1.radius references the radius in circle1, and circle1.getArea() instance variable
invokes the getArea function on circle1. Functions are invoked as operations on objects. member function
instance function
The data field radius is referred to as an instance member variable or simply instance
variable, because it is dependent on a specific instance. For the same reason, the function calling object
getArea is referred to as an instance member function or instance function, because you can
invoke it only on a specific instance. The object on which an instance function is invoked is
called a calling object.

Note class naming convention
object naming convention
When you define a custom class, capitalize the first letter of each word in a class
name—for example, the class names Circle, Rectangle, and Desk. The class
names in the C++ library are named in lowercase. The objects are named like variables.

The following points on classes and objects are worth noting:

■ You can use primitive data types to define variables. You can also use class names to

declare object names. In this sense, a class is also a data type. class is a type

■ In C++, you can use the assignment operator = to copy the contents from one object memberwise copy
to the other. By default, each data field of one object is copied to its counterpart in
the other object. For example,

circle2 = circle1;

copies the radius in circle1 to circle2. After the copy, circle1 and circle2
are still two different objects but have the same radius.

■ Object names are like array names. Once an object name is declared, it represents constant object name
an object. It cannot be reassigned to represent another object. In this sense, an object
name is a constant, though the contents of the object may change. Memberwise copy
can change an object’s contents but not its name.

■ An object contains data and may invoke functions. This may lead you to think that an object size
object is quite large. It isn’t, though. Data are physically stored in an object, but func-
tions are not. Since functions are shared by all objects of the same class, the compiler
creates just one copy for sharing. You can find out the actual size of an object using
the sizeof function. For example, the following code displays the size of objects
circle1 and circle2. Their size is 8, since the data field radius is double, which
takes 8 bytes.

Circle circle1;
Circle circle2(5.0);

cout << sizeof(circle1) << endl;
cout << sizeof(circle2) << endl;

350 Chapter 9 Objects and Classes

anonymous objects Usually you create a named object and later access its members through its name. Occa-
sionally you may create an object and use it only once. In this case, you don’t have to name it.
Such objects are called anonymous objects.

The syntax to create an anonymous object using the no-arg constructor is

ClassName()

The syntax to create an anonymous object using the constructor with arguments is

ClassName(arguments)

For example,

circle1 = Circle();

creates a Circle object using the no-arg constructor and copies its contents to circle1.

circle1 = Circle(5);

creates a Circle object with radius 5 and copies its contents to circle1.
For example, the following code creates Circle objects and invokes their getArea()

function.

cout << "Area is " << Circle().getArea() << endl;
cout << "Area is " << Circle(5).getArea() << endl;

As you see from these examples, you may create an anonymous object if it will not be
referenced later.

no-arg constructor Caution

Please note that in C++, to create an anonymous object using the no-arg constructor,
you have to add parentheses after the constructor name (e.g., Circle()). To create
a named object using the no-arg constructor, you cannot use the parentheses after the
constructor name (e.g., you use Circle circle1 rather than Circle circle1()).
This is the required syntax, which you just have to accept.

✓Check 9.1 Describe the relationship between an object and its defining class. How do you
Point
define a class? How do you declare and create an object?

9.2 What are the differences between constructors and functions?

9.3 How do you create an object using a no-arg constructor? How do you create an

object using a constructor with arguments?

9.4 Once an object name is declared, can it be reassigned to reference another

object?

9.5 Assuming that the Circle class is defined as in Listing 9.1, show the printout of

the following code:

Circle c1(5);
Circle c2(6);
c1 = c2;
cout << c1.radius << " " << c2.radius << endl;

9.6 What is wrong in the following code? (Use the Circle class defined in Listing 9.1,

TestCircle.cpp.)

int main() 9.6 Separating Class Definition from Implementation 351
{
int main()
Circle c1(); {
cout << c1.getRadius() << endl;
Circle c1(5);
return 0; Circle c1(6);
} return 0;
}
(a)
(b)

9.7 What is wrong in the following code?

class Circle
{
public:

Circle()
{
}
double radius = 1;
};

9.8 Which of the following statements is correct?

Circle c;

Circle c();

9.9 Suppose the following two are independent statements. Are they correct?

Circle c;

Circle c = Circle();

9.6 Separating Class Definition from Implementation VideoNote

Separating class definition from class implementation makes the class easy to Separate class definition
maintain.
Key
C++ allows you to separate class definition from implementation. The class definition Point
describes the contract of the class and the class implementation carries out the contract. The
class definition simply lists all the data fields, constructor prototypes, and function prototypes.
The class implementation implements the constructors and functions. The class definition and
implementation may be in two separate files. Both files should have the same name but differ-
ent extension names. The class definition file has an extension name .h (h means header) and
the class implementation file an extension name .cpp.

Listings 9.3 and 9.4 present the Circle class definition and implementation.

LISTING 9.3 Circle.h data field
no-arg constructor
1 class Circle
2{
3 public:
4 // The radius of this circle
5 double radius;
6
7 // Construct a default circle object
8 Circle();

352 Chapter 9 Objects and Classes

second constructor 9
10 // Construct a circle object
function prototype 11 Circle(double);
semicolon required 12
13 // Return the area of this circle
14 double getArea();
15 };

don’t omit semicolon Caution

It is a common mistake to omit the semicolon (;) at the end of the class definition.

include class definition LISTING 9.4 Circle.cpp
implement constructor
1 #include "Circle.h"
implement constructor 2
3 // Construct a default circle object
implement function 4 Circle::Circle()
binary scope resolution 5{
6 radius = 1;
operator 7}
client 8
9 // Construct a circle object
10 Circle::Circle(double newRadius)
11 {
12 radius = newRadius;
13 }
14
15 // Return the area of this circle
16 double Circle::getArea()
17 {
18 return radius * radius * 3.14159;
19 }

The :: symbol, known as the binary scope resolution operator, specifies the scope of a
class member in a class.

Here, Circle:: preceding each constructor and function in the Circle class tells the
compiler that these constructors and functions are defined in the Circle class.

Listing 9.5 is a program that uses the Circle class. Such a program that uses the class is
often referred to as a client of the class.

include class definition LISTING 9.5 TestCircleWithHeader.cpp
construct circle
construct circle 1 #include <iostream>
2 #include "Circle.h"
set a new radius 3 using namespace std;
4
5 int main()
6{
7 Circle circle1;
8 Circle circle2(5.0);
9
10 cout << "The area of the circle of radius "
11 << circle1.radius << " is " << circle1.getArea() << endl;
12 cout << "The area of the circle of radius "
13 << circle2.radius << " is " << circle2.getArea() << endl;
14
15 // Modify circle radius
16 circle2.radius = 100;

9.6 Separating Class Definition from Implementation 353

17 cout << "The area of the circle of radius "
18 << circle2.radius << " is " << circle2.getArea() << endl;
19
20 return 0;
21 }

The area of the circle of radius 1 is 3.14159
The area of the circle of radius 5 is 78.5397
The area of the circle of radius 100 is 31415.9

There are at least two benefits for separating a class definition from implementation. why separation?

1. It hides implementation from definition. You can feel free to change the implementation.
The client program that uses the class does not need to change as long as the definition is
not changed.

2. As a software vendor, you can just provide the customer with the header file and class
object code without revealing the source code for implementing the class. This protects
the software vendor’s intellectual property.

Note compile from command line

To compile a main program from the command line, you need to add all its supporting
files in the command. For example, to compile TestCircleWithDefinition.cpp using a
GNU C++ compiler, the command is

g++ Circle.h Circle.cpp TestCircleWithHeader.cpp –o Main

Note compile from IDE

If the main program uses other programs, all of these program source files must be present
in the project pane in the IDE. Otherwise, you may get linking errors. For example, to run
TestCircleWithHeader.cpp, you need to place TestCircleWithHeader.cpp,
Circle.cpp, and Circle.h in the project pane in Visual C++, as shown in Figure 9.5.

Add .h files
here
Add .cpp
files here

FIGURE 9.5 For the program to run, you need to place all dependent files in the project pane.

354 Chapter 9 Objects and Classes

✓Check 9.10 How do you separate class definition from implementation?
Point 9.11
What is the output of the following code? (Use the Circle class defined in
Listing 9.3, Circle.h.)

int main() int main()
{ {

Circle c1; cout << Circle(8).getArea()
Circle c2(6); << endl;
c1 = c2;
cout << c1.getArea() << endl; return 0;
}
return 0;
} (b)

(a)

9.7 Preventing Multiple Inclusions

Key Inclusion guard prevents header files to be included multiple times.
Point
It is a common mistake to include, inadvertently, the same header file in a program multi-
ple times. Suppose Head.h includes Circle.h and TestHead.cpp includes both Head.h and
Circle.h, as shown in Listings 9.6 and 9.7.

include Circle.h LISTING 9.6 Head.h

1 #include "Circle.h"
2 // Other code in Head.h omitted

include Circle.h LISTING 9.7 TestHead.cpp
include Head.h
1 #include "Circle.h"
inclusion guard 2 #include "Head.h"
is symbol defined? 3
define symbol 4 int main()
5{
6 // Other code in TestHead.cpp omitted
7}

If you compile TestHead.cpp, you will get a compile error indicating that there are multi-
ple definitions for Circle. What is wrong here? Recall that the C++ preprocessor inserts the
contents of the header file at the position where the header is included. Circle.h is included in
line 1. Since the header file for Circle is also included in Head.h (see line 1 in Listing 9.6),
the preprocessor will add the definition for the Circle class another time as result of includ-
ing Head.h in TestHead.cpp, which causes the multiple-inclusion errors.

The C++ #ifndef directive along with the #define directive can be used to prevent a
header file from being included multiple times. This is known as inclusion guard. To make
this work, you have to add three lines to the header file. The three lines are highlighted in
Listing 9.8.

LISTING 9.8 CircleWithInclusionGuard.h

1 #ifndef CIRCLE_H
2 #define CIRCLE_H
3
4 class Circle
5{
6 public:

9.8 Inline Functions in Classes 355

7 // The radius of this circle end of #ifndef
8 double radius;
9
10 // Construct a default circle object
11 Circle();
12
13 // Construct a circle object
14 Circle(double);
15
16 // Return the area of this circle
17 double getArea();
18 };
19
20 #endif

Recall that the statements preceded by the pound sign (#) are preprocessor directives. They
are interpreted by the C++ preprocessor. The preprocessor directive #ifndef stands for “if not
defined.” Line 1 tests whether the symbol CIRCLE_H is already defined. If not, define the symbol
in line 2 using the #define directive and the rest of the header file is included; otherwise, the rest
of the header file is skipped. The #endif directive is needed to indicate the end of header file.

To avoid multiple-inclusion errors, define a class using the following template and conven-
tion for naming the symbol:

#ifndef ClassName_H
#define ClassName_H

A class header for the class named ClassName

#endif

If you replace Circle.h by CircleWithInclusionGuard.h in Listings 9.6 and 9.7, the program
will not have the multiple-inclusion error.

9.12 What might cause multiple-inclusion errors? How do you prevent multiple ✓Check
9.13 inclusions of header files? Point

What is the #define directive for?

9.8 Inline Functions in Classes Key
Point
You can define short functions as inline functions to improve performance.
inline definition
Section 6.10, “Inline Functions,” introduced how to improve function efficiency using inline
functions. When a function is implemented inside a class definition, it automatically becomes an
inline function. This is also known as inline definition. For example, in the following definition for
class A, the constructor and function f1 are automatically inline functions, but function f2 is not.

class A
{
public:

A()
{

// Do something;
}

double f1()
{

// Return a number
}

356 Chapter 9 Objects and Classes

double f2();
};

There is another way to define inline functions for classes. You may define inline functions
in the class’s implementation file. For example, to define function f2 as an inline function,
precede the inline keyword in the function header as follows:

// Implement function as inline
inline double A::f2()
{

// Return a number
}

As noted in Section 6.10, short functions are good candidates for inline functions, but long
functions are not.

✓Check 9.14 How do you implement all functions inline in Listing 9.4, Circle.cpp?
Point
9.9 Data Field Encapsulation
Key
Point Making data fields private protects data and makes the class easy to maintain.
The data fields radius in the Circle class in Listing 9.1 can be modified directly (e.g.,
circle1.radius = 5). This is not a good practice—for two reasons:

■ First, data may be tampered with.

■ Second, it makes the class difficult to maintain and vulnerable to bugs. Suppose you
want to modify the Circle class to ensure that the radius is nonnegative after other
programs have already used the class. You have to change not only the Circle class,
but also the programs that use the Circle class. This is because the clients may have
modified the radius directly (e.g., myCircle.radius = -5).

data field encapsulation To prevent direct modifications of properties, you should declare the data field private,
private using the private keyword. This is known as data field encapsulation. Making the radius
data field private in the Circle class, you can define the class as follows:

class Circle
{
public:

Circle();
Circle(double);
double getArea();

private:
double radius;

};

A private data field cannot be accessed by an object through a direct reference outside
the class that defines the private field. But often a client needs to retrieve and/or modify
a data field. To make a private data field accessible, provide a get function to return the
field’s value. To enable a private data field to be updated, provide a set function to set a
new value.

accessor Note
mutator
Colloquially, a get function is referred to as an accessor, and a set function is referred
to as a mutator.

9.9 Data Field Encapsulation 357

A get function has the following signature:

returnType getPropertyName()

If the returnType is bool, by convention the get function should be defined as follows: bool accessor

bool isPropertyName()

A set function has the following signature:

void setPropertyName(dataType propertyValue)

Let us create a new circle class with a private data field radius and its associated acces-
sor and mutator functions. The class diagram is shown in Figure 9.6. The new circle class is
defined in Listing 9.9.

The - sign indicates Circle The radius of this circle (default: 1.0).
private modifier -radius: double
Constructs a default circle object.
+Circle() Constructs a circle object with the specified radius.
+Circle(radius: double) Returns the radius of this circle.
+getRadius(): double Sets a new radius for this circle.
+setRadius(radius: double): void Returns the area of this circle.
+getArea(): double

FIGURE 9.6 The Circle class encapsulates circle properties and provides get/set and other functions.

LISTING 9.9 CircleWithPrivateDataFields.h public
access function
1 #ifndef CIRCLE_H mutator function
2 #define CIRCLE_H private
3
4 class Circle include header file
5{ constructor
6 public:
7 Circle();
8 Circle(double);
9 double getArea();
10 double getRadius();
11 void setRadius(double);
12
13 private:
14 double radius;
15 };
16
17 #endif

Listing 9.10 implements the class contract specified in the header file in Listing 9.9.

LISTING 9.10 CircleWithPrivateDataFields.cpp

1 #include "CircleWithPrivateDataFields.h"
2
3 // Construct a default circle object
4 Circle::Circle()

358 Chapter 9 Objects and Classes

constructor 5{
get area 6 radius = 1;
get radius 7}
set radius 8
9 // Construct a circle object
include header file 10 Circle::Circle(double newRadius)
construct object 11 {
construct object 12 radius = newRadius;
get radius 13 }
set radius 14
15 // Return the area of this circle
16 double Circle::getArea()
17 {
18 return radius * radius * 3.14159;
19 }
20
21 // Return the radius of this circle
22 double Circle::getRadius()
23 {
24 return radius;
25 }
26
27 // Set a new radius
28 void Circle::setRadius(double newRadius)
29 {
30 radius = (newRadius >= 0) ? newRadius : 0;
31 }

The getRadius() function (lines 22–25) returns the radius, and the setRadius
(newRadius) function (line 28–31) sets a new radius into the object. If the new radius is
negative, 0 is set to the radius in the object. Since these functions are the only ways to read
and modify radius, you have total control over how the radius property is accessed. If you
have to change the functions’ implementation, you need not change the client programs. This
makes the class easy to maintain.

Listing 9.11 is a client program that uses the Circle class to create a Circle object and
modifies the radius using the setRadius function.

LISTING 9.11 TestCircleWithPrivateDataFields.cpp

1 #include <iostream>
2 #include "CircleWithPrivateDataFields.h"
3 using namespace std;
4
5 int main()
6{
7 Circle circle1;
8 Circle circle2(5.0);
9
10 cout << "The area of the circle of radius "
11 << circle1.getRadius() << " is " << circle1.getArea() << endl;
12 cout << "The area of the circle of radius "
13 << circle2.getRadius() << " is " << circle2.getArea() << endl;
14
15 // Modify circle radius
16 circle2.setRadius(100);
17 cout << "The area of the circle of radius "
18 << circle2.getRadius() << " is " << circle2.getArea() << endl;
19
20 return 0;
21 }

9.10 The Scope of Variables 359

The area of the circle of radius 1 is 3.14159
The area of the circle of radius 5 is 78.5397
The area of the circle of radius 100 is 31415.9

The data field radius is declared private. Private data can be accessed only within their
defining class. You cannot use circle1.radius in the client program. A compile error
would occur if you attempted to access private data from a client.

Tip

To prevent data from being tampered with and to make the class easy to maintain, the
data fields in this book will be private.

9.15 What is wrong in the following code? (Use the Circle class defined in Listing 9.9, ✓Check
CircleWithPrivateDataFields.h.) Point
9.16
9.17 Circle c;
cout << c.radius << endl;

What is an accessor function? What is a mutator function? What are the naming
conventions for such functions?

What are the benefits of data field encapsulation?

9.10 The Scope of Variables Key
Point
The scope of instance and static variables is the entire class, regardless of where the
variables are declared.

Chapter 6 discussed the scope of global variables, local variables, and static local variables.
Global variables are declared outside all functions and are accessible to all functions in its
scope. The scope of a global variable starts from its declaration and continues to the end of
the program. Local variables are defined inside functions. The scope of a local variable starts
from its declaration and continues to the end of the block that contains the variable. Static
local variables are permanently stored in the program so they can be used in the next call of
the function.

The data fields are declared as variables and are accessible to all constructors and functions
in the class. Data fields and functions can be in any order in a class. For example, all the fol-
lowing declarations are the same:

class Circle class Circle class Circle
{ { {
public: public: private:

Circle(); Circle(); double radius;
Circle(double); Circle(double);
double getArea(); public:
double getRadius(); private: double getArea();
void setRadius(double); double radius; double getRadius();
void setRadius(double);
private: public:
double radius; double getArea(); public:
double getRadius(); Circle();
}; void setRadius(double); Circle(double);

}; };

(a) (b) (c)

360 Chapter 9 Objects and Classes

public first Tip

Though the class members can be in any order, the common style in C++ is to place
public members first and then private members.

This section discusses the scope rules of all the variables in the context of a class.
You can declare a variable for data field only once, but you can declare the same variable
name in a function many times in different functions.
Local variables are declared and used inside a function locally. If a local variable has the
same name as a data field, the local variable takes precedence, and the data field with the same
name is hidden. For example, in the program in Listing 9.12, x is defined as a data field and
as a local variable in the function.

data field x LISTING 9.12 HideDataField.cpp
data field y
no-arg constructor 1 #include <iostream>
2 using namespace std;
local variable 3
4 class Foo
create object 5{
invoke function 6 public:
7 int x; // Data field
8 int y; // Data field
9
10 Foo()
11 {
12 x = 10;
13 y = 10;
14 }
15
16 void p()
17 {
18 int x = 20; // Local variable
19 cout << "x is " << x << endl;
20 cout << "y is " << y << endl;
21 }
22 };
23
24 int main()
25 {
26 Foo foo;
27 foo.p();
28
29 return 0;
30 }

x is 20
y is 10

Why is the printout 20 for x and 10 for y? Here is why:

■ x is declared as a data field in the Foo class, but is also defined as a local variable in
the function p() with an initial value of 20. The latter x is displayed to the console
in line 19.

■ y is declared as a data field, so it is accessible inside function p().

9.11 Class Abstraction and Encapsulation 361

Tip ✓Check
Point
As demonstrated in the example, it is easy to make mistakes. To avoid confusion, do not
declare the same variable name twice in a class, except for function parameters.

9.18 Can data fields and functions be placed in any order in a class?

9.11 Class Abstraction and Encapsulation VideoNote

Class abstraction is the separation of class implementation from the use of a class. The The Loan class
details of implementation are encapsulated and hidden from the user. This is known as
class encapsulation. Key
Point

In Chapter 6 you learned about function abstraction and used it in stepwise program develop- class abstraction
ment. C++ provides many levels of abstraction. Class abstraction is the separation of class
implementation from the use of a class. The creator of a class provides a description of the class’s contract
class and lets the user know how it can be used. The collection of functions and fields that class encapsulation
are accessible from outside the class, together with the description of how these members are
expected to behave, serves as the class’s contract. As shown in Figure 9.7, the user of the
class does not need to know how the class is implemented. The details of implementation are
encapsulated and hidden from the user. This is known as class encapsulation. For example,
you can create a Circle object and find the area of the circle without knowing how the area
is computed.

Class implementation Class Class Contract Clients use the
is like a black box (function class through the
hidden from the clients contract of the class
prototypes and
public constants)

FIGURE 9.7 Class abstraction separates class implementation from the use of the class.

Class abstraction and encapsulation are two sides of the same coin. Many real-life exam-
ples illustrate the concept of class abstraction. Consider, for instance, building a computer
system. Your personal computer is made up of many components, such as a CPU, CD-ROM,
floppy disk, motherboard, fan, and so on. Each component can be viewed as an object that has
properties and functions. To get the components to work together, all you need to know is how
each component is used and how it interacts with the others. You don’t need to know how it
works internally. The internal implementation is encapsulated and hidden from you. You can
build a computer without knowing how a component is implemented.

The computer-system analogy precisely mirrors the object-oriented approach. Each com-
ponent can be viewed as an object of the class for the component. For example, you might
have a class that models all kinds of fans for use in a computer, with properties like fan size
and speed, functions like start, stop, and so on. A specific fan is an instance of this class with
specific property values.

As another example, consider getting a loan. A specific loan can be viewed as an object
of a Loan class. Interest rate, loan amount, and loan period are its data properties, and com-
puting monthly payment and total payment are its functions. When you buy a car, a loan
object is created by instantiating the class with your loan interest rate, loan amount, and
loan period. You can then use the functions to find the monthly payment and total payment
of your loan. As a user of the Loan class, you don’t need to know how these functions are
implemented.

362 Chapter 9 Objects and Classes

Let us use the Loan class as an example to demonstrate the creation and use of classes.
Loan has the data fields annualInterestRate, numberOfYears, and loanAmount, and
the functions getAnnualInterestRate, getNumberOfYears, getLoanAmount,
setAnnualInterestRate, setNumberOfYears, setLoanAmount, getMonthlyPayment,
and getTotalPayment, as shown in Figure 9.8.

Loan The annual interest rate of the loan (default: 2.5).
The number of years for the loan (default: 1)
-annualInterestRate: double The loan amount (default: 1000).
-numberOfYears: int
-loanAmount: double Constructs a default loan object.
Constructs a loan with specified interest rate, years,
+Loan() and loan amount.
+Loan(rate: double,years: int,
Returns the annual interest rate of this loan.
amount: double) Returns the number of the years of this loan.
Returns the amount of this loan.
+getAnnualInterestRate(): double Sets a new annual interest rate to this loan.
+getNumberOfYears(): int
+getLoanAmount(): double Sets a new number of years to this loan.
+setAnnualInterestRate(
Sets a new amount to this loan.
rate: double): void
+setNumberOfYears( Returns the monthly payment of this loan.
Returns the total payment of this loan.
years: int): void
+setLoanAmount(

amount: double): void
+getMonthlyPayment(): double
+getTotalPayment(): double

FIGURE 9.8 The Loan class models the properties and behaviors of loans.

public functions The UML diagram in Figure 9.8 serves as the contract for the Loan class. Throughout the
private fields book, you will play the role of both class user and class developer. The user can use the class
without knowing how the class is implemented. Assume that the Loan class is available, with
the header file, as shown in Listing 9.13. Let us begin by writing a test program that uses the
Loan class, in Listing 9.14.

LISTING 9.13 Loan.h

1 #ifndef LOAN_H
2 #define LOAN_H
3
4 class Loan
5{
6 public:
7 Loan();
8 Loan(double rate, int years, double amount);
9 double getAnnualInterestRate();
10 int getNumberOfYears();
11 double getLoanAmount();
12 void setAnnualInterestRate(double rate);
13 void setNumberOfYears(int years);
14 void setLoanAmount(double amount);
15 double getMonthlyPayment();
16 double getTotalPayment();
17
18 private:
19 double annualInterestRate;

9.11 Class Abstraction and Encapsulation 363

20 int numberOfYears;
21 double loanAmount;
22 };
23
24 #endif

LISTING 9.14 TestLoanClass.cpp include Loan header

1 #include <iostream> input number of years
2 #include <iomanip> input loan amount
3 #include "Loan.h" create Loan object
4 using namespace std; monthly payment
5 total payment
6 int main()
7{
8 // Enter annual interest rate
9 cout << "Enter yearly interest rate, for example 8.25: ";
10 double annualInterestRate;
11 cin >> annualInterestRate;
12
13 // Enter number of years
14 cout << "Enter number of years as an integer, for example 5: ";
15 int numberOfYears;
16 cin >> numberOfYears;
17
18 // Enter loan amount
19 cout << "Enter loan amount, for example 120000.95: ";
20 double loanAmount;
21 cin >> loanAmount;
22
23 // Create Loan object
24 Loan loan(annualInterestRate, numberOfYears, loanAmount);
25
26 // Display results
27 cout << fixed << setprecision(2);
28 cout << "The monthly payment is "
29 << loan.getMonthlyPayment() << endl;
30 cout << "The total payment is " << loan.getTotalPayment() << endl;
31
32 return 0;
33 }
34

The main function reads interest rate, payment period (in years), and loan amount (lines
8–21), creates a Loan object (line 24), and then obtains the monthly payment (line 29) and
total payment (line 30) using the instance functions in the Loan class.

The Loan class can be implemented as in Listing 9.15.

LISTING 9.15 Loan.cpp no-arg constructor

1 #include "Loan.h"
2 #include <cmath>
3 using namespace std;
4
5 Loan::Loan()
6{
7 annualInterestRate = 9.5;
8 numberOfYears = 30;
9 loanAmount = 100000;
10 }

364 Chapter 9 Objects and Classes

constructor 11
12 Loan::Loan(double rate, int years, double amount)
accessor function 13 {
accessor function 14 annualInterestRate = rate;
accessor function 15 numberOfYears = years;
mutator function 16 loanAmount = amount;
mutator function 17 }
mutator function 18
get monthly payment 19 double Loan::getAnnualInterestRate()
20 {
get total payment 21 return annualInterestRate;
22 }
23
24 int Loan::getNumberOfYears()
25 {
26 return numberOfYears;
27 }
28
29 double Loan::getLoanAmount()
30 {
31 return loanAmount;
32 }
33
34 void Loan::setAnnualInterestRate(double rate)
35 {
36 annualInterestRate = rate;
37 }
38
39 void Loan::setNumberOfYears(int years)
40 {
41 numberOfYears = years;
42 }
43
44 void Loan::setLoanAmount(double amount)
45 {
46 loanAmount = amount;
47 }
48
49 double Loan::getMonthlyPayment()
50 {
51 double monthlyInterestRate = annualInterestRate / 1200;
52 return loanAmount * monthlyInterestRate / (1 -
53 (pow(1 / (1 + monthlyInterestRate), numberOfYears * 12)));
54 }
55
56 double Loan::getTotalPayment()
57 {
58 return getMonthlyPayment() * numberOfYears * 12;
59 }

From a class developer’s perspective, a class is designed for use by many different custom-
ers. In order to be useful in a wide range of applications, a class should provide a variety of
ways for customization through constructors, properties, and functions.

The Loan class contains two constructors, three get functions, three set functions, and
the functions for finding monthly payment and total payment. You can construct a Loan
object by using the no-arg constructor or the one with three parameters: annual interest
rate, number of years, and loan amount. The three get functions, getAnnualInterest,
getNumberOfYears, and getLoanAmount, return annual interest rate, payment years, and
loan amount, respectively.

Important Pedagogical Tip Key Terms 365

The UML diagram for the Loan class is shown in Figure 9.8. Students should begin by ✓Check
writing a test program that uses the Loan class even though they don’t know how the Point
Loan class is implemented. This has three benefits:

■ It demonstrates that developing a class and using a class are two separate tasks.
■ It enables you to skip the complex implementation of certain classes without inter-

rupting the sequence of the book.
■ It is easier to learn how to implement a class if you are familiar with the class

through using it.

For all the examples from now on, you may first create an object from the class and try
to use its functions before turning your attention to its implementation.

9.19 What is the output of the following code? (Use the Loan class defined in

Listing 9.13, Loan.h.)

#include <iostream>
#include "Loan.h"
using namespace std;

class A
{
public:

Loan loan;
int i;
};

int main()
{

A a;
cout << a.loan.getLoanAmount() << endl;
cout << a.i << endl;

return 0;
}

KEY TERMS

accessor 356 352 inline definition 355
anonymous object 350 instance 342
binary scope resolution operator (::) instance function 349 342
calling object 349 instance variable 349
class 342 instantiation 342
class abstraction 361 member function 349
class encapsulation 361 member access operator 349
client 352 mutator 356
constructor 342 no-arg constructor 348
constructor initializer list 348 object 342
contract 342 object-oriented programming (OOP)
data field 342 property 342
data field encapsulation 356 private 356
default constructor 348 public 345
dot operator (.) 349 state 342
inclusion guard 354 UML class diagram 343

366 Chapter 9 Objects and Classes

CHAPTER SUMMARY

1. A class is a blueprint for objects.

2. A class defines the data fields for storing the properties of objects and provides

constructors for creating objects and functions for manipulating them.

3. Constructors must have the same name as the class itself.

4. A non-arg constructor is a constructor that does not have arguments.

5. A class is also a data type. You can use it to declare and create objects.

6. An object is an instance of a class. You use the dot (.) operator to access members of

that object through its name.

7. The state of an object is represented by data fields (also known as properties) with their

current values.

8. The behavior of an object is defined by a set of functions.

9. The data fields do not have initial values. They must be initialized in constructors.

10. You can separate class definition from class implementation by defining class in a

header file and class implementation in a separate file.

11. The C++ #ifndef directive, called inclusion guard, can be used to prevent a header file

from being included multiple times.

12. When a function is implemented inside a class definition, it automatically becomes an

inline function.

13. Visibility keywords specify how the class, function, and data are accessed.

14. A public function or data is accessible to all clients.

15. A private function or data is accessible only inside the class.

16. You can provide a get function or a set function to enable clients to see or modify the data.

17. Colloquially, a get function is referred to as a getter (or accessor), and a set function is

referred to as a setter (or mutator).

18. A get function has the signature

returnType getPropertyName()

19. If the returnType is bool, the get function should be defined as

bool isPropertyName().

20. A set function has the signature

void setPropertyName(dataType propertyValue)

Programming Exercises 367

QUIZ

Answer the quiz for this chapter online at www.cs.armstrong.edu/liang/cpp3e/quiz.html.

PROGRAMMING EXERCISES

Pedagogical Note three objectives

The exercises achieve three objectives:

1. Design and draw UML for classes;

2. Implement classes from the UML;

3. Use classes to develop applications.

Solutions for the UML diagrams for the even-numbered exercises can be downloaded from the
Companion Website and all others from the Instructor Web site.

Sections 9.2–9.11

9.1 (The Rectangle class) Design a class named Rectangle to represent a rectangle.

The class contains:

■ Two double data fields named width and height that specify the width and
height of the rectangle.

■ A no-arg constructor that creates a rectangle with width 1 and height 1.
■ A constructor that creates a default rectangle with the specified width and

height.
■ The accessor and mutator functions for all the data fields.
■ A function named getArea() that returns the area of this rectangle.
■ A function named getPerimeter() that returns the perimeter.

Draw the UML diagram for the class. Implement the class. Write a test program
that creates two Rectangle objects. Assign width 4 and height 40 to the first
object and width 3.5 and height 35.9 to the second. Display the properties of both
objects and find their areas and perimeters.

9.2 (The Fan class) Design a class named Fan to represent a fan. The class contains:

■ An int data field named speed that specifies the speed of the fan. A fan has VideoNote
three speeds indicated with a value 1, 2, or 3.
The Fan class
■ A bool data field named on that specifies whether the fan is on.
■ A double data field named radius that specifies the radius of the fan.
■ A no-arg constructor that creates a default fan with speed 1, on false, and

radius 5.
■ The accessor and mutator functions for all the data fields.

Draw the UML diagram for the class. Implement the class. Write a test program
that creates two Fan objects. Assign speed 3, radius 10, and turn it on to the first
object. Assign speed 2, radius 5, and turn it off to the second object. Invoke their
accessor functions to display the fan properties.

9.3 (The Account class) Design a class named Account that contains:

■ An int data field named id for the account.
■ A double data field named balance for the account.
■ A double data field named annualInterestRate that stores the current

interest rate.

368 Chapter 9 Objects and Classes

■ A no-arg constructor that creates a default account with id 0, balance 0, and
annualInterestRate 0.

■ The accessor and mutator functions for id, balance, and
annualInterestRate.

■ A function named getMonthlyInterestRate() that returns the monthly
interest rate.

■ A function named withdraw(amount) that withdraws a specified amount
from the account.

■ A function named deposit(amount) that deposits a specified amount to the
account.

Draw the UML diagram for the class. Implement the class. Write a test program that
creates an Account object with an account ID of 1122, a balance of 20000, and an
annual interest rate of 4.5%. Use the withdraw function to withdraw $2500, use
the deposit function to deposit $3000, and print the balance, the monthly interest.

9.4 (The MyPoint class) Design a class named MyPoint to represent a point with x-

and y-coordinates. The class contains:

■ Two data fields x and y that represent the coordinates.
■ A no-arg constructor that creates a point (0, 0).
■ A constructor that constructs a point with specified coordinates.
■ Two get functions for data fields x and y, respectively.
■ A function named distance that returns the distance from this point to another

point of the MyPoint type.

*9.5 Draw the UML diagram for the class. Implement the class. Write a test program
that creates two points (0, 0) and (10, 30.5) and displays the distance between
them.

(The Time class) Design a class named Time. The class contains:

■ Data fields hour, minute, and second that represent a time.
■ A no-arg constructor that creates a Time object for the current time.
■ A constructor that constructs a Time object with a specified elapse time since

the middle of night, Jan 1, 1970, in seconds.
■ A constructor that constructs a Time object with the specified hour, minute, and

second.
■ Three get functions for the data fields hour, minute, and second.
■ A function named setTime(int elapseTime) that sets a new time for the

object using the elapsed time.

*9.6 Draw the UML diagram for the class. Implement the class. Write a test program
that creates two Time objects, one using a no-arg constructor and the other using
Time(555550), and display their hour, minute, and second.

(Hint: The first two constructors will extract hour, minute, and second from the
elapse time. For example, if the elapse time is 555550 seconds, the hour is 10,
the minute is 19, and the second is 9. For the no-arg constructor, the current time
can be obtained using time(0), as shown in Listing 2.9, ShowCurrentTime.cpp.)

(Algebra: quadratic equations) Design a class named QuadraticEquation for a
quadratic equation ax2 + bx + x = 0. The class contains:

■ Data fields a, b, and c that represent three coefficients.

■ A constructor for the arguments for a, b, and c.

■ Three get functions for a, b, and c.

■ A function named getDiscriminant() that returns the discriminant, which is
b2 - 4ac.

Programming Exercises 369

■ The functions named getRoot1() and getRoot2() for returning two roots of
the equation:

r1 = -b + 2b2 - 4ac = -b - 2b2 - 4ac
2a and r2 2a

*9.7 These functions are useful only if the discriminant is nonnegative. Let these func-
tions return 0 if the discriminant is negative.

Draw the UML diagram for the class. Implement the class. Write a test program
that prompts the user to enter values for a, b, and c, and displays the result based
on the discriminant. If the discriminant is positive, display the two roots. If the
discriminant is 0, display the one root. Otherwise, display "The equation has
no real roots".

(Stopwatch) Design a class named StopWatch. The class contains:

■ Private data fields startTime and endTime with get functions.
■ A no-arg constructor that initializes startTime with the current time.
■ A function named start() that resets the startTime to current time.
■ A function named stop() that sets the endTime to current time.
■ A function named getElapsedTime() that returns the elapsed time for the

stop watch in milliseconds.

*9.8 Draw the UML diagram for the class. Implement the class. Write a test
program that measures the execution time of sorting 100000 numbers using
selection sort.

(The Date class) Design a class named Date. The class contains:

■ Data fields year, month, and day that represent a date.
■ A no-arg constructor that creates a Date object for the current date.
■ A constructor that constructs a Date object with a specified elapse time since

the middle of night, Jan 1, 1970, in seconds.
■ A constructor that constructs a Date object with the specified year, month, and

day.
■ Three get functions for the data fields year, month, and day.
■ A function named setDate(int elapseTime) that sets a new date for the

object using the elapsed time.

*9.9 Draw the UML diagram for the class. Implement the class. Write a test program
that creates two Date objects, one using a no-arg constructor and the other using
Date(555550), and display their year, month, and day.

(Hint: The first two constructors will extract year, month, and day from the elapse
time. For example, if the elapse time is 561555550 seconds, the year is 1987, the
month is 10, and the day is 17. For the no-arg constructor, the current date can be
obtained using time(0), as shown in Listing 2.9, ShowCurrentTime.cpp.)

(Algebra: 2 * 2 linear equations) Design a class named LinearEquation for a
2 * 2 system of linear equations:

ax + by = e ed - bf af - ec
cx + dy = f x = ad - bc y = ad - bc

The class contains:

■ Private data fields a, b, c, d, e, and f.
■ A constructor with the arguments for a, b, c, d, e, and f.

370 Chapter 9 Objects and Classes

■ Six get functions for a, b, c, d, e, and f.
■ A function named isSolvable() that returns true if ad - bc is not 0.
■ Functions getX() and getY() that return the solution for the equation.

**9.10 Draw the UML diagram for the class and then implement the class. Write a test
**9.11 program that prompts the user to enter a, b, c, d, e, and f and displays the result.
If ad - bc is 0, report that “The equation has no solution.” See Programming
Exercise 3.3 for sample runs.

(Geometry: intersection) Suppose two line segments intersect. The two endpoints
for the first line segment are (x1, y1) and (x2, y2) and for the second line segment
are (x3, y3) and (x4, y4). Write a program that prompts the user to enter these four
endpoints and displays the intersecting point. Use the LinearEquation class in
Exercise 9.9 for finding the interesting point. See Programming Exercise 3.22 for
sample runs.

(The EvenNumber class) Define the EvenNumber class for representing an even
number. The class contains:

■ A data field value of the int type that represents the integer value stored in the
object.

■ A no-arg constructor that creates an EvenNumber object for the value 0.
■ A constructor that constructs an EvenNumber object with the specified value.
■ A function named getValue() to return an int value for this object.
■ A function named getNext() to return an EvenNumber object that represents

the next even number after the current even number in this object.
■ A function named getPrevious() to return an EvenNumber object that rep-

resents the previous even number before the current even number in this object.

Draw the UML diagram for the class. Implement the class. Write a test program
that creates an EvenNumber object for value 16 and invokes the getNext() and
getPrevious() functions to obtain and displays these numbers.

CHAPTER

10

OBJECT-ORIENTED
THINKING

Objectives

■ To process strings using the string class (§10.2).
■ To develop functions with object arguments (§10.3).
■ To store and process objects in arrays (§10.4).
■ To distinguish between instance and static variables and functions

(§10.5).
■ To define constant functions to prevent data fields from being

modified accidentally (§10.6).
■ To explore the differences between the procedural paradigm and

object-oriented paradigm (§10.7).
■ To design a class for body mass index (§10.7).
■ To develop classes for modeling composition relationships (§10.8).
■ To design a class for a stack (§10.9).
■ To design classes that follow the class design guidelines (§10.10).

372 Chapter 10 Object-Oriented Thinking

10.1 Introduction

Key The focus of this chapter is on class design and explores the differences between
Point
procedural programming and object-oriented programming.

Chapter 9 introduced the important concept of objects and classes. You learned how to define
classes, create objects, and use objects. This book’s approach is to teach problem solving
and fundamental programming techniques before object-oriented programming. This chapter
addresses the transition from procedural to object-oriented programming. Students will see
the benefits of object-oriented programming and use it effectively.

Our focus here is on class design. We will use several examples to illustrate the advantages
of the object-oriented approach. The first example is the string class provided in the C++
library. The other examples involve designing new classes and using them in applications. We
will also introduce some language features supporting these examples.

10.2 The string Class

VideoNote Key The string class defines the string type in C++. It contains many useful functions
Point
The string class for manipulating strings.

In C++ there are two ways to process strings. One way is to treat them as arrays of characters
ending with the null terminator ('\0'), as discussed in Section 7.11, “C-Strings.” These are
known as C-strings. The null terminator indicates the end of the string, which is important for
the C-string functions to work. The other way is to process strings using the string class.
You can use the C-string functions to manipulate and process strings, but the string class is
easier. Processing C-strings requires the programmer to know how characters are stored in the
array. The string class hides the low-level storage from the programmer. The programmer
is freed from implementation details.

Section 4.8, “The string Type,” briefly introduced the string type. You learned how to
retrieve a string character using the at(index) function and the subscript operator [], and
use the size() and length() functions to return the number of characters in a string. This
section gives a more detailed discussion on using string objects.

empty string 10.2.1 Constructing a String
C-string to string
You created a string using a syntax like this:

string s = "Welcome to C++";

This statement is not efficient because it takes two steps. It first creates a string object using a
string literal and then copies the object to s.

A better way to create a string is to use the string constructor like this:

string s("Welcome to C++");

You can create an empty string using string’s no-arg constructor. For example, the follow-
ing statement creates an empty string:

string s;

You can also create a string from a C-string using string’s constructor as shown in the fol-
lowing code:

char s1[] = "Good morning";
string s(s1);

Here s1 is a C-string and s is a string object.

10.2 The string Class 373

10.2.2 Appending to a String

You can use several overloaded functions to add new contents to a string, as shown in
Figure 10.1.

string Appends string s into this string object.
+append(s: string): string Appends n number of characters in s starting at the position
+append(s: string, index: int, n: int): string
index to this string.
+append(s: string, n: int): string
+append(n: int, ch: char): string Appends the first n number of characters in s to this string.
Appends n copies of character ch to this string.

FIGURE 10.1 The string class provides the functions for appending a string.

For example:

string s1("Welcome");
s1.append(" to C++"); // Appends " to C++" to s1
cout << s1 << endl; // s1 now becomes Welcome to C++

string s2("Welcome");
s2.append(" to C and C++", 0, 5); // Appends " to C" to s2
cout << s2 << endl; // s2 now becomes Welcome to C

string s3("Welcome");
s3.append(" to C and C++", 5); // Appends " to C" to s3
cout << s3 << endl; // s3 now becomes Welcome to C

string s4("Welcome");
s4.append(4, 'G'); // Appends "GGGG" to s4
cout << s4 << endl; // s4 now becomes WelcomeGGGG

10.2.3 Assigning a String

You can use several overloaded functions to assign new contents to a string, as shown in
Figure 10.2.

string Assigns array of characters or a string s to this string.
+assign(s[]: char): string Assigns string s to this string.
+assign(s: string): string Assigns n number of characters in s starting at the position
+assign(s: string, index: int, n: int): string
index to this string.
+assign(s: string, n: int): string Assigns the first n number of characters in s to this string.
+assign(n: int, ch: char): string Assigns n copies of character ch to this string.

FIGURE 10.2 The string class provides the functions for assigning a string.

For example:

string s1("Welcome");
s1.assign("Dallas"); // Assigns "Dallas" to s1
cout << s1 << endl; // s1 now becomes Dallas

374 Chapter 10 Object-Oriented Thinking

string s2("Welcome");
s2.assign("Dallas, Texas", 0, 5); // Assigns "Dalla" to s2
cout << s2 << endl; // s2 now becomes Dalla

string s3("Welcome");
s3.assign("Dallas, Texas", 5); // Assigns "Dalla" to s3
cout << s3 << endl; // s3 now becomes Dalla

string s4("Welcome");
s4.assign(4, 'G'); // Assigns "GGGG" to s4
cout << s4 << endl; // s4 now becomes GGGG

10.2.4 Functions at, clear, erase, and empty

You can use the at(index) function to retrieve a character at a specified index, clear() to
clear the string, erase(index, n) to delete part of the string, and empty() to test whether
a string is empty, as shown in Figure 10.3.

string Returns the character at the position index from this string.
Removes all characters in this string.
+at(index: int): char Removes n characters from this string starting at position index.
+clear(): void Returns true if this string is empty.
+erase(index: int, n: int): string
+empty(): bool

FIGURE 10.3 The string class provides the functions for retrieving a character, clearing and erasing a string,
and checking whether a string is empty.

For example:

string s1("Welcome");
cout << s1.at(3) << endl; // s1.at(3) returns c
cout << s1.erase(2, 3) << endl; // s1 is now Weme
s1.clear(); // s1 is now empty
cout << s1.empty() << endl; // s1.empty returns 1 (means true)

10.2.5 Functions length, size, capacity, and c_str()

You can use the functions length(), size(), and capacity() to obtain a string’s length,
size, and capacity and c_str() to return a C-string, as shown in Figure 10.4. The functions
length() and size() are aliases. The functions c_str() and data() are the same in
the new C++11. The capacity() function returns the internal buffer size which is always
greater than or equal to the actual string size.

string Returns the number of characters in this string.
Same as length().
+length(): int Returns the size of the storage allocated for this string.
+size(): int Returns a C-string for this string.
+capacity(): int Same as c_str().
+c_str(): char[]
+data(): char[]

FIGURE 10.4 The string class provides the functions for getting the length, capacity, and C-string of the string.

10.2 The string Class 375

For example, see the following code: create string
erase two characters
1 string s1("Welcome");
2 cout << s1.length() << endl; // Length is 7
3 cout << s1.size() << endl; // Size is 7
4 cout << s1.capacity() << endl; // Capacity is 15
5
6 s1.erase(1, 2);
7 cout << s1.length() << endl; // Length is now 5
8 cout << s1.size() << endl; // Size is now 5
9 cout << s1.capacity() << endl; // Capacity is still 15

Note capacity?

The capacity is set to 15 when string s1 is created in line 1. After two characters are
erased in line 6, the capacity is still 15, but the length and size become 5.

10.2.6 Comparing Strings

Often, in a program, you need to compare the contents of two strings. You can use the compare
function. This function returns an int value greater than 0, 0, or less than 0 if this string is
greater than, equal to, or less than the other string, as shown in Figure 10.5.

string Returns a value greater than 0, 0, or less than 0 if this string is
+compare(s: string): int greater than, equal to, or less than s.

+compare(index: int, n: int, s: string): int Compares this string with substring s(index, …, index ϩ nϪ1).

FIGURE 10.5 The string class provides the functions for comparing strings.

For example:

string s1("Welcome");
string s2("Welcomg");
cout << s1.compare(s2) << endl; // Returns –1
cout << s2.compare(s1) << endl; // Returns 1
cout << s1.compare("Welcome") << endl; // Returns 0

10.2.7 Obtaining Substrings

You can obtain a single character from a string using the at function. You can also obtain a
substring from a string using the substr function, as shown in Figure 10.6.

string Returns a substring of n characters from this string starting at
+substr(index: int, n: int): string position index.

+substr(index: int): string Returns a substring of this string starting at position index.

FIGURE 10.6 The string class provides the functions for obtaining substrings.

For example:

string s1("Welcome");
cout << s1.substr(0, 1) << endl; // Returns W

376 Chapter 10 Object-Oriented Thinking

cout << s1.substr(3) << endl; // Returns come
cout << s1.substr(3, 3) << endl; // Returns com

10.2.8 Searching in a String

You can use the find function to search for a substring or a character in a string, as shown in
Figure 10.7. The function returns string::npos (not a position) if no match is found. npos
is a constant defined in the string class.

string Returns the position of the first matching character for ch.
+find(ch: char): unsigned
+find(ch: char, index: int): unsigned Returns the position of the first matching character for ch at or
from the position index.
+find(s: string): unsigned
+find(s: string, index: int): unsigned Returns the position of the first matching substring s.

Returns the position of the first matching substring s starting at
or from the position index.

FIGURE 10.7 The string class provides the functions for finding substrings.

For example:

string s1("Welcome to HTML");
cout << s1.find("co") << endl; // Returns 3
cout << s1.find("co", 6) << endl; // Returns string::npos
cout << s1.find('o') << endl; // Returns 4
cout << s1.find('o', 6) << endl; // Returns 9

10.2.9 Inserting and Replacing Strings

You can use the insert and replace functions to insert a substring and replace a substring
in a string, as shown in Figure 10.8.

String Inserts the string s into this string at position index.

+insert(index: int, s: string): string Inserts the character ch n times into this string at position index.
+insert(index: int, n: int, ch: char): string
+replace(index: int, n: int, s: string): string Replaces the n characters starting at position index in this string
with the string s.

FIGURE 10.8 The string class provides the functions for inserting and replacing substrings.

Here are examples of using the insert and replace functions:

string s1("Welcome to HTML");
s1.insert(11, "C++ and ");
cout << s1 << endl; // s1 becomes Welcome to C++ and HTML

string s2("AA");
s2.insert(1, 4, 'B');
cout << s2 << endl; // s2 becomes to ABBBBA

string s3("Welcome to HTML");
s3.replace(11, 4, "C++");
cout << s3 << endl; // s3 becomes Welcome to C++

10.2 The string Class 377

Note return string

A string object invokes the append, assign, erase, replace, and insert
functions to change the contents of the string object. These functions also return
the new string. For example, in the following code, s1 invokes the insert function to
insert "C++ and " into s1, and the new string is returned and assigned to s2.

string s1("Welcome to HTML");
string s2 = s1.insert(11, "C++ and ");
cout << s1 << endl; // s1 becomes Welcome to C++ and HTML
cout << s2 << endl; // s2 becomes Welcome to C++ and HTML

Note capacity too small?

On most compilers, the capacity is automatically increased to accommodate more char-
acters for the functions append, assign, insert, and replace. If the capacity is
fixed and is too small, the function will copy as many characters as possible.

10.2.10 String Operators

C++ supports operators to simplify string operations. Table 10.1 lists the string operators.

TABLE 10.1 String Operators

Operator Description

[] Accesses characters using the array subscript operator.
= Copies the contents of one string to the other.
+ Concatenates two strings into a new string.
+= Appends the contents of one string to the other.
<< Inserts a string to a stream
>> Extracts characters from a stream to a string delimited by a whitespace
or the null terminator character.
==, !=, <, Six relational operators for comparing strings.
<=, >, >=

Here are the examples to use these operators: =

string s1 = "ABC"; // The = operator []
string s2 = s1; // The = operator
for (int i = s2.size() – 1; i >= 0; i--) +
<<
cout << s2[i]; // The [] operator +=

string s3 = s1 + "DEFG"; // The + operator ==
cout << s3 << endl; // s3 becomes ABCDEFG !=
>
s1 += "ABC"; >=
cout << s1 << endl; // s1 becomes ABCABC <
<=
s1 = "ABC";
s2 = "ABE";
cout << (s1 == s2) << endl; // Displays 0 (means false)
cout << (s1 != s2) << endl; // Displays 1 (means true)
cout << (s1 > s2) << endl; // Displays 0 (means false)
cout << (s1 >= s2) << endl; // Displays 0 (means false)
cout << (s1 < s2) << endl; // Displays 1 (means true)
cout << (s1 <= s2) << endl; // Displays 1 (means true)

378 Chapter 10 Object-Oriented Thinking

number to stringstream 10.2.11 Converting Numbers to Strings
stringstream to string
Section 7.11.6, “Conversion between Strings and Numbers,” introduced how to convert a
string to an integer and a floating-point number using the functions atoi and atof. You can
also use the itoa function to convert an integer to a string. Sometimes you need to convert a
floating-point number to a string. You can write a function to perform the conversion. How-
ever, a simple approach is to use the stringstream class in the <sstream> header. string-
stream provides an interface to manipulate strings as if they were input/output streams. One
application of stringstream is for converting numbers to strings. Here is an example:

1 stringstream ss;
2 ss << 3.1415;
3 string s = ss.str();

include sstream header 10.2.12 Splitting Strings
include string header
Often you need to extract the words from a string. Assume that the words are separated by
create stringstream whitespaces. You can use the stringstream class discussed in the preceding section to
accomplish this task. Listing 10.1 gives an example that extracts the words from a string and
end of stream displays the words in separate lines.
get data from stream
LISTING 10.1 ExtractWords.cpp

1 #include <iostream>
2 #include <sstream>
3 #include <string>
4 using namespace std;
5
6 int main()
7{
8 string text("Programming is fun");
9 stringstream ss(text);
10
11 cout << "The words in the text are " << endl;
12 string word;
13 while (!ss.eof())
14 {
15 ss >> word;
16 cout << word << endl;
17 }
18
19 return 0;
20 }

The words in the text are
Programming
is
fun

The program creates a stringstream object for the text string (line 9) and this object
can be used just like an input stream for reading data from the console. It sends data from the
string stream to a string object word (line 15). The eof() function in the stringstream
class returns true when all items in string stream are read (line 13).


Click to View FlipBook Version