|
Table of Contents
Learning C++:
An Index of Entry Points
2. The A reference document on the basic elements of C++.
3. The Patterns
|
A. A Second Look at the 'for' Statement
When we discussed the 'for' statement in chapter 3,
Section VIII. B, we saw that it had three distinct parts within the
parentheses - with the first part used to initialize any variables, the
second part used to test the stopping conditions, and the third part used
to increment variables if necessary. In the code above, there are two
possible stopping conditions so each is tested in the second part. One can
read this as "Keep looping as long as 'index' is less than 'numContracts'
AND 'found' is FALSE". Note how the parts of a 'for' statement are
separated by semicolons, while separate elements within a part are
separated by commas. Note also that in this example, the variable 'index' is used in the
loop but not declared in the loop. Up to now, we have usually written code
such as:
with the word 'int' included in the parentheses. This is simply a
matter of convenience - if one needs a variable for a 'for' loop and the
variable has not been declared, do so when you initialize the variable. In
the example here, however, we are making a quick change to existing code.
In that code 'index' is already declared, so let's take advantage of that
fact and not declare it again. It turns out that the 'for' statement is one of the most versatile
statements in C++. We shall see more of this versatility later. A second change we might consider making
involves the repeated use of the same search code in 'Add', 'Delete' and
'ReplaceContract'. You can see that each of these member functions has the
same lines of code: Why not make this code a separate function called by all three
functions using this code. This new function would only be used by member
functions, so it could be declared as private to the class. (Code using
instances of this class would still have access to 'FindContract' for
doing searches.) Note that this idea of private functions is not something
foreign to the way the 'real world' operates. Organizations often have
procedures known only within the organization. That is part of what makes
organizations different from each other. The first step in this change is to declare our new function, call it
'Search', as private to the class. Here is a fragment of the modified .h
file for 'ListOfContracts' showing this declaration: Note that 'Search' is the only function declared in the private
part of the class. Because all the other functions must be available to
programs using this class, they are declared as public functions. 'Search'
should be unavailable outside the class just as the data members are
unavailable so it is declared as private. In other words, 'Search' and the
data members are all encapsulated. Regarding the declaration itself: all the searches use the contractID,
so it must be received by the function. A careful look at the old code
might lead you to expect that this function should return a Boolean, since
all the searches set a variable 'found' to true or false. Unfortunately,
there is a small complication here that won't let us do that. The member
functions, 'Delete' and 'ReplaceContract', both need to know the location
of the contract to be deleted or replaced. If our 'Search' function just
returns true or false, these functions will not know where the contract
was found. Therefore, we will return the location where the contract was
found, that is, the value of 'index'. Note that if 'index' has been
incremented so much that it has the value found in 'numContracts', we know
that the list has been fully searched and the ID was not found. (Remember,
'numContracts' holds the location of the next free element of the
array of contracts. Thus, if 'Search' returns the value in 'numContracts'
(through the value of 'index'), it is an indication that all contracts
were examined and none matched.) A look at the definition for 'Search' might help. We will use a 'for'
loop version, just to show some variation. Since 'Search' is a member function of 'ListOfContracts' (even
if it is a private member function) we must include ' ListOfContracts
::' in the first line of the definition. Inside, the 'for' statement
only has one test condition because we again take advantage of the effect
of the 'return' statement to end processing. As you can see, the value of
'index' is returned. If the sought after contract ID is found, the index
of the matching element is returned. If the loop completes, it is because
index has reached the value of 'numContracts' and this is returned to
indicate the failure to find a match. Now that we have this function, we can
simplify each of the functions that used to do their own searching.
Consider 'ReplaceContract': The ID of the contract to be inserted is retrieved; the search
is made; and, if the value returned by "Search (index)" is less than
'numContracts', the replacement takes place. Note that it is much easier
to understand this function with the details of the search moved out. As
noted earlier, this is an important advantage in using functional
decomposition. The other two functions, as rewritten, are included below. The one thing to point out about this code is the way the 'Add'
function checks to see if a contract already exists with the ID of the
proposed new contract. This is accomplished in the line: In other words, if 'index' equals 'numContracts', we know the search
routine went through the whole list of contracts without finding a
match. You might have noticed that we did not modify 'FindContract' to use
'Search'. You are encouraged to try this as an exercise.
Topics Covered in the "Essentials of C++"
|