Previous Section Main Menu Next Section

CHAPTER 8

AN EVEN BETTER CONTRACT PROGRAM


Section V: Class Declarations for Contract and ListOfContracts Section I: Analyzing the Code Implications of an Improved Contract Program Section II:Instances as Array Elements Section III: The List: A Look at Data Representation
Section IV: Lists: Working with Encapsulation Section VI: Member Functions for ListOfContracts Section VII: Improving ListOfContracts Section VIII: Rewriting the Nonmember Functions

Section V. Class Declarations for Contract and ListOfContracts
The good news is that we are finally ready to code. The bad news is that the program will have to be extensively modified to deal with the problems we just discussed. The bad news, however, is not as bad as it seems. Usually, when a program needs to be rewritten, it turns out that much of the code already written can be used - just in a modified form. The difficulty in the rewriting process comes more from being careful to write code that works than in the actual typing.

A. Preprocessor Directives
To make sure this program works, we should start from the VERY beginning. If we created our own Boolean type (see Chapter 6, Section III, Part 'B'), this means starting with the file 'common.h'. This file includes the declarations necessary for the user-defined type, Boolean. A potential problem occurs in the fact that the Boolean type is used in both classes and in the main program.

Suppose we include the line:

#include "common.h"

in both class declaration files. Remember that the #include preprocessor directive instructs the system to copy the contents of a file into the file containing the directive. In other words, both class declaration files will have the code found in 'common.h'. There is no problem here until we write the main program with '#include' commands to copy in both class declaration files. Now, all the code found in both files is copied into the main program which means that the code from 'common.h is included twice! That file has the lines:

const Boolean TRUE = 1;
const Boolean FALSE = 0;

which will result in an error because the constants TRUE and FALSE would be defined twice!

This problem occurs all the time in C++, so there is a simple solution. You should place another set of preprocessor directives:

#ifndef some_name
#define some_name

at the top of all '.h' files ( 'dot h' files - meaning files that end in '.h' and are used as 'include' files).

And, at the bottom of all '.h' files include the line:

#endif

Here is 'common.h' with the added code:

// A set of basic type and function declarations common to many programs

When the system sees the new lines, it acts as follows:

The line

#ifndef COMMON_H

asks the question, "Has the term 'COMMON_H' been defined yet?" The first time the file 'common.h' is read into a piece of code, the answer is no and the next line is executed. This line,

'#define COMMON_H'

defines the term 'COMMON_H'. Afterwards, the rest of the lines are executed ending with the line

'#endif'

and the system goes to the rest of the code in the file that has directly or indirectly included 'common.h'.

If these lines are encountered again in the file, as they would be in the case of our main program, the line,

#ifndef COMMON_H

is again processed but this time 'COMMON_H' has already been defined so the lines from here to the line,

'#endif'

are skipped! Thus, the constants TRUE and FALSE are not declared and defined again and there is no error. Note the purpose of the '#endif'. Without it, the system would not know how many lines to skip.

That is the only change in the file 'common.h'. With the existence of the built-in 'bool' type, there is no reason to use this 'common.h' file. However, it is strongly recommended that you get in the habit of always including the three lines:

in your '.h' files. Any term can be substituted for 'some_name', but it is common to use a set of letters made up of the file name followed by _H. That is where 'COMMON_H' came from in our example. Using such a convention makes it clear what you are doing and helps you avoid using a similar name elsewhere in your code.

With the 'Contract' class the new code could look as follows:

 

B. Redeclaring the Contract Class
We now move onto the declarations for the class 'Contract'. The need for an ID property in the this class causes a few additions to the class declaration:

This new code can be viewed under the file name contrct2.h.

The file containing the definitions for this class, 'contrct2.cpp' also has some changes:



C. The 'ListOfContracts' Class
Now it is time to declare the class 'ListfOfContracts'. There is no new C++ to learn here here, but the way C++ features are used is different and should be carefully studied. This is very common in programming languages, as it is in any language - the same basic building blocks can be put together in many novel ways.

// Class Declarations for ListOfContracts
// File: ch8list1.h

#ifndef LIST1_H
#define LIST1_H

#include "common.h"
#include "contrct2.h"  // Uses the modified version of the contract class.

const int MAX_CONTRACTS = 5;	// arbitrary number chosen for test purposes

typedef Contract ContractArray[MAX_CONTRACTS];


class ListOfContracts
{public:
	ListOfContracts();
   	/*
		Purpose:	To instantiate (create) an instance of the class 'ListOfContracts'.
		Goal:		A new instance of class 'ListOfContracts' now exists

		Receives:	NONE
		RETURNS:	NONE
	*/

	void Add(Contract contract);
	/*
		Purpose:	To add an instance of the class 'Contract' to the list.
		Goal:		A new instance of class 'contract' is on the list

		Receives:	a contract
		Returns: 	NONE:
	*/


	void Delete(int contractNum);
	/*
		Purpose:	To delete an instance of the class 'Contract' from the list.
		Goal:		The instance of class 'contract' is deleted

		Receives:	 A contract number
		Returns: 	NONE:
	*/

	bool FindContract(int ID, Contract& contract);
	/*
		Purpose:	To find out if a contract is in the list and, if so, return it.
		Goal:		If the list holds a contract with id 'ID', the function 
				returns that contract in the variable 'contract' and 
				the function returns true
				If not, the function returns false and 'contract' holds garbage.'

		Receives:   	A contract ID
		Returns:	Whether or not the contract was found AND, if found, the 
				contract itself.
	*/

	void ReplaceContract (Contract contract);
	/*
		Purpose:	To replace the properties of one contract in the list.
		Goal:    	The properties of the contract in the list with the ID of
				'contract' have been replaced. If there is no contract on the list
				with this ID, an error message is displayed.


		Receives:	A contract
		Returns:	NONE
	*/

	void DisplayAll();
	/*
		Purpose:	To display all the contracts in the list.
		Goal:		All the contracts are displayed on the screen

		Receives:	NONE
		Returns:	NONE
	*/


 private:
	int numContracts;  	// indicates the number of contracts on the list and the next
                       		// available slot in list

	ContractArray listOfContracts;

};

#endif
The first thing to observe is that the constant and type definitions have been moved from the file containing 'main' to here. The main program will no longer have any use for the array itself. It will only concern itself with the user defined types 'Contract' and 'ListOfContracts'. Being more precise, the programmer for the main program will have no use for arrays. Remember the idea behind the object oriented paradigm: Once a class, along with its properties and behaviors, are defined by some programmer, other programmers can use that class without caring at all how the internal structure or behavior of that class is implemented.

Students have a tendency to fight this idea, but it really is key to the way we function as humans. How many people know the principles of aerodynamics that allow a plane to fly? Does that stop people from flying? How many of us can explain how a microwave works? Not being able to provide such an explanation does not stop us from using a microwave on a regular basis. Given this, how is it so strange to think of one programmer designing a class and other programmers using it as if it were a 'black box' whose internals are unknown to the programmer-user? (And, by the way, this idea of a 'black box' is just what the idea of encapsulation is all about.)

What confuses people sometimes is that it is possible for one programmer to act as both the designer and user of a class. However, even this is typical human behavior. A person who designs airplanes probably does not think about such designs as he or she is flying to visit grand-ma. As a matter of fact, it is likely that he or she does everything possible to keep from thinking about the design so as to accomplish other things while flying. Maintaining awareness of the internal workings of the airplane - or worse, listening for 'noises' - only makes it difficult for him or her to focus on other tasks. Similarly, once you as a programmer are finished with work on a class or a function, it is best to forget about the inner workings of your code, or you will not be able to put your full attention on the next task.

Topics Covered in the "Essentials of C++"

Preprocessor Directives

Top of Section Main Menu Next Section