| |
Main Menu | Next Section |
Note that the single line inside this function is similar to the
line above to delete the array pointed to by the variable 'ptr'.
In most cases destructors will be this simple and short.
Now let's examine the constructor:
ListOfContracts :: ListOfContracts()
{
numContracts = 0;
presentMax = CONTRACT_GROWTH;
listOfContracts = new Contract[CONTRACT_GROWTH];
}
This follows the algorithm we discussed above. Our goal
is to start with an empty list that has CONTRACT_GROWTH elements
in it. Thus we set numContracts to 0, set the size of the list
(presentMax) to CONTRACT_GROWTH, request enough memory for the
number of contracts equivalent to CONTRACT_GROWTH, and save the
address of that array in 'listOfContracts'. Figure 10.10 shows how memory looks after an instance, called 'thisInstance', of 'ListOfContracts' is instantiated with this constructor.
The next member function to discuss is 'Add'. Before reading the
commentary, compare the code below with the algorithm we previously
discussed.
void ListOfContracts :: Add(Contract contract)
{ int contractNum = contract.ProvideID();
int index = Search(contractNum);
if (index == numContracts) // contract with this ID does not exist
{ if (numContracts == presentMax) // Need add contract but no room
{ IncreaseSize();
}
listOfContracts[numContracts] = contract; // copy contract into list
numContracts++;
}
else
{ cout << "\nA contract with this ID already exists.\n";
}
}
The main difference between this and the version from chapter
8 occurs once the code has determined that the contract ID does
not exist in the list and, therefore, the contract can be added.
The code:
{
IncreaseSize();
checks to see if all the slots in the array have been used, and
if so, it calls 'IncreaseSize'. We will examine this new function
in a moment. First, notice the two lines after this call:
They are the same code used in the previous version and, because
they are outside the brackets for the 'if' statement that checks
to see if the array is full, they are executed regardless of whether
the array has enough room. In other words, the code first checks
to see if the array is full. If there is still room, the code
does the add. If not, the array is increased in size and then
the add is done. The add statement is always executed. It is simply
a matter of making sure that there is enough room for the add,
either because the array is not yet full or because the array's
size has been increased.
As we have done so often before, note that we are able to talk
about 'IncreaseSize' and assume that it accomplishes its task
without any idea of how it does so. Having said that, it is now
time to check out that 'how'. Again, please review the algorithm
for this function first.
void ListOfContracts :: IncreaseSize()
{ presentMax += CONTRACT_GROWTH;
Contract* tempArray = new Contract[presentMax]; // create new list
for (int index = 0; index < numContracts; index++)
{ tempArray[index] = listOfContracts[index];
}
delete [] listOfContracts;
listOfContracts = tempArray;
}
To review: this tells the compiler that this function belongs
to the class 'ListOfContracts and therefore has access to the
member data for whichever instance is under consideration. Combined
with the fact that the class declaration included this function
declaration in the private part, we know that this function is
only available to other member functions of this class. Functions
belonging to other classes and functions that are not part of
any class (the functions in the main program file) cannot call
this function.
If you have studied the algorithm carefully, you know that the code follows it closely. (It better or why have the algorithm!) The size of 'presentMax' is increased, and the code then asks for enough memory for an array of contracts of this new size. The address of this array is stored in 'tempArray' and a 'for' loop is used to copy the contracts in the old array to this new array. This copy is made because we want to return the memory used by the old array to the system. That 'return' is accomplished by the line:
Note again the use of the empty []'s.
Finally, the address held in 'tempArray' is copied to 'listOfContracts'
so that the instance has access to the array. When the function
returns, 'listOfContracts' points to a bigger array and the 'Add'
function will take advantage of this. Note that the variable 'tempArray',
since it is a local variable, will disappear. However, since the
code does not explicitly request it, the memory pointed to by
'tempArray' is not returned to the system. If you are unclear about this, you might want to review figures 10.1 through 10.4 above.
That finishes the discussion of the class 'ListOfContracts'. Nothing
else changes in the definitions. For the complete code of the
definitions click 'here'
B. Putting It All Together Again
Here is an important point. We have made extensive changes to
"ListOfContracts' but none of them involve that class's interface.
In other words, since no new public functions were added and no changes were made to the receives or returns of the public functions belonging to 'ListOfContracts', the modified code for this class can be used without any changes to the 'Contract' code or to the main program.
This is important because it demonstrates that a programming project can be divided among a number of programmers who can each go their own way and not have to be constantly communicating with each other after they have all agreed on the basic design and interface. Imagine that this is a much more complex program, and that the three parts (the Contract class, the ListOfContracts' class, and the code that uses these classes) are much more complex, with each part requiring long days of coding by a separate programmer.
The programmer in charge of 'ListOfContracts' could write a "quick
and dirty" version of the code and provide it to the other
programmers to allow them to test their parts. He or she could
then go back and make the code 'right'. When finished, he or she
could then provide this new, improved version of the code to the
others, and they would not have to make any changes in their own
code. Here you see the power of encapsulation and the object-oriented
paradigm.
Of course, seeing is believing. Bring the code for the contract
class (common2.h, contrct4.h, and contrct4.cpp), the list of contracts class (c10lst1a.h and c10lst1a.cpp), and the main program (c10tst1a.cpp) into your compiler and link them.
| |
Main Menu | Next Section |