Placing a Class in a Separate File for Reusability

We have developed class GradeBook as far as we need to for now from a programming perspective, so let's consider some software engineering issues. One of the benefits of creating class definitions is that, when packaged properly, our classes can be reused by programmerspotentially worldwide. For example, we can reuse C++ Standard Library type string in any C++ program by including the header file in the program (and, as we will see, by being able to link to the library's object code).

Unfortunately, programmers who wish to use our GradeBook class cannot simply include the file from Fig. 3.7 in another program. As you learned in Chapter 2, function main begins the execution of every program, and every program must have exactly one main function. If other programmers include the code from Fig. 3.7, they get extra baggageour main functionand their programs will then have two main functions. When they attempt to compile their programs, the compiler will indicate an error because, again, each program can have only one main function. For example, attempting to compile a program with two main functions in Microsoft Visual C++ .NET produces the error

error C2084: function 'int main(void)' already has a body

when the compiler tries to compile the second main function it encounters. Similarly, the GNU C++ compiler produces the error

redefinition of 'int main()'

These errors indicate that a program already has a main function. So, placing main in the same file with a class definition prevents that class from being reused by other programs. In this section, we demonstrate how to make class GradeBook reusable by separating it into another file from the main function.

Header Files

Each of the previous examples in the chapter consists of a single .cpp file, also known as a source-code file, that contains a GradeBook class definition and a main function. When building an object-oriented C++ program, it is customary to define reusable source code (such as a class) in a file that by convention has a .h filename extensionknown as a header file. Programs use #include preprocessor directives to include header files and take advantage of reusable software components, such as type string provided in the C++ Standard Library and user-defined types like class GradeBook.

In our next example, we separate the code from Fig. 3.7 into two filesGradeBook.h (Fig. 3.9) and fig03_10.cpp (Fig. 3.10). As you look at the header file in Fig. 3.9, notice that it contains only the GradeBook class definition (lines 1141) and lines 38, which allow class GradeBook to use cout, endl and type string. The main function that uses class GradeBook is defined in the source-code file fig03_10.cpp (Fig. 3.10) at lines 1021. To help you prepare for the larger programs you will encounter later in this book and in industry, we often use a separate source-code file containing function main to test our classes (this is called a driver program). You will soon learn how a source-code file with main can use the class definition found in a header file to create objects of a class.

Figure 3.9. GradeBook class definition.

(This item is displayed on pages 96 - 97 in the print version)

 1 // Fig. 3.9: GradeBook.h
 2 // GradeBook class definition in a separate file from main.
 3 #include 
 4 using std::cout;
 5 using std::endl;
 7 #include  // class GradeBook uses C++ standard string class
 8 using std::string;
10 // GradeBook class definition
11 class GradeBook
12 {
13 public:
14 // constructor initializes courseName with string supplied as argument
15 GradeBook( string name )
16 {
17 setCourseName( name ); // call set function to initialize courseName
18 } // end GradeBook constructor
20 // function to set the course name
21 void setCourseName( string name )
22 {
23 courseName = name; // store the course name in the object
24 } // end function setCourseName
26 // function to get the course name
27 string getCourseName()
28 {
29 return courseName; // return object's courseName
30 } // end function getCourseName
32 // display a welcome message to the GradeBook user
33 void displayMessage()
34 {
35 // call getCourseName to get the courseName
36 cout << "Welcome to the grade book for
" << getCourseName()
37 << "!" << endl;
38 } // end function displayMessage
39 private:
40 string courseName; // course name for this GradeBook
41 }; // end class GradeBook

Including a Header File That Contains a User-Defined Class

A header file such as GradeBook.h (Fig. 3.9) cannot be used to begin program execution, because it does not contain a main function. If you try to compile and link GradeBook.h by itself to create an executable application, Microsoft Visual C++ .NET will produce the linker error message:

error LNK2019: unresolved external symbol _main referenced in
function _mainCRTStartup

Running GNU C++ on Linux produces a linker error message containing:

undefined reference to 'main'

This error indicates that the linker could not locate the program's main function. To test class GradeBook (defined in Fig. 3.9), you must write a separate source-code file containing a main function (such as Fig. 3.10) that instantiates and uses objects of the class.

Figure 3.10. Including class GradeBook from file GradeBook.h for use in main.

 1 // Fig. 3.10: fig03_10.cpp
 2 // Including class GradeBook from file GradeBook.h for use in main.
 3 #include 
 4 using std::cout;
 5 using std::endl;
 7 #include "GradeBook.h" // include definition of class GradeBook
 9 // function main begins program execution
10 int main()
11 {
12 // create two GradeBook objects
13 GradeBook gradeBook1( "CS101 Introduction to C++ Programming" );
14 GradeBook gradeBook2( "CS102 Data Structures in C++" );
16 // display initial value of courseName for each GradeBook
17 cout << "gradeBook1 created for course: " << gradeBook1.getCourseName()
18 << "
gradeBook2 created for course: " << gradeBook2.getCourseName()
19 << endl;
20 return 0; // indicate successful termination
21 } // end main
 gradeBook1 created for course: CS101 Introduction to C++ Programming
 gradeBook2 created for course: CS102 Data Structures in C++

Recall from Section 3.4 that, while the compiler knows what fundamental data types like int are, the compiler does not know what a GradeBook is because it is a user-defined type. In fact, the compiler does not even know the classes in the C++ Standard Library. To help it understand how to use a class, we must explicitly provide the compiler with the class's definitionthat's why, for example, to use type string, a program must include the header file. This enables the compiler to determine the amount of memory that it must reserve for each object of the class and ensure that a program calls the class's member functions correctly.

To create GradeBook objects gradeBook1 and gradeBook2 in lines 1314 of Fig. 3.10, the compiler must know the size of a GradeBook object. While objects conceptually contain data members and member functions, C++ objects typically contain only data. The compiler creates only one copy of the class's member functions and shares that copy among all the class's objects. Each object, of course, needs its own copy of the class's data members, because their contents can vary among objects (such as two different BankAccount objects having two different balance data members). The member function code, however, is not modifiable, so it can be shared among all objects of the class. Therefore, the size of an object depends on the amount of memory required to store the class's data members. By including GradeBook.h in line 7, we give the compiler access to the information it needs (Fig. 3.9, line 40) to determine the size of a GradeBook object and to determine whether objects of the class are used correctly (in lines 1314 and 1718 of Fig. 3.10).

Line 7 instructs the C++ preprocessor to replace the directive with a copy of the contents of GradeBook.h (i.e., the GradeBook class definition) before the program is compiled. When the source-code file fig03_10.cpp is compiled, it now contains the GradeBook class definition (because of the #include), and the compiler is able to determine how to create GradeBook objects and see that their member functions are called correctly. Now that the class definition is in a header file (without a main function), we can include that header in any program that needs to reuse our GradeBook class.

How Header Files Are Located

Notice that the name of the GradeBook.h header file in line 7 of Fig. 3.10 is enclosed in quotes (" ") rather than angle brackets (< >). Normally, a program's source-code files and user-defined header files are placed in the same directory. When the preprocessor encounters a header file name in quotes (e.g., "GradeBook.h"), the preprocessor attempts to locate the header file in the same directory as the file in which the #include directive appears. If the preprocessor cannot find the header file in that directory, it searches for it in the same location(s) as the C++ Standard Library header files. When the preprocessor encounters a header file name in angle brackets (e.g., ), it assumes that the header is part of the C++ Standard Library and does not look in the directory of the program that is being preprocessed.

Error-Prevention Tip 3.3

To ensure that the preprocessor can locate header files correctly, #include preprocessor directives should place the names of user-defined header files in quotes (e.g., "GradeBook.h") and place the names of C++ Standard Library header files in angle brackets (e.g., ).


Additional Software Engineering Issues

Now that class GradeBook is defined in a header file, the class is reusable. Unfortunately, placing a class definition in a header file as in Fig. 3.9 still reveals the entire implementation of the class to the class's clientsGradeBook.h is simply a text file that anyone can open and read. Conventional software engineering wisdom says that to use an object of a class, the client code needs to know only what member functions to call, what arguments to provide to each member function and what return type to expect from each member function. The client code does not need to know how those functions are implemented.

If client code does know how a class is implemented, the client code programmer might write client code based on the class's implementation details. Ideally, if that implementation changes, the class's clients should not have to change. Hiding the class's implementation details makes it easier to change the class's implementation while minimizing, and hopefully eliminating, changes to client code.

In Section 3.9, we show how to break up the GradeBook class into two files so that

  1. the class is reusable
  2. the clients of the class know what member functions the class provides, how to call them and what return types to expect
  3. the clients do not know how the class's member functions are implemented.

Introduction to Computers, the Internet and World Wide Web

Introduction to C++ Programming

Introduction to Classes and Objects

Control Statements: Part 1

Control Statements: Part 2

Functions and an Introduction to Recursion

Arrays and Vectors

Pointers and Pointer-Based Strings

Classes: A Deeper Look, Part 1

Classes: A Deeper Look, Part 2

Operator Overloading; String and Array Objects

Object-Oriented Programming: Inheritance

Object-Oriented Programming: Polymorphism


Stream Input/Output

Exception Handling

File Processing

Class string and String Stream Processing

Web Programming

Searching and Sorting

Data Structures

Bits, Characters, C-Strings and structs

Standard Template Library (STL)

Other Topics

Appendix A. Operator Precedence and Associativity Chart

Appendix B. ASCII Character Set

Appendix C. Fundamental Types

Appendix D. Number Systems

Appendix E. C Legacy Code Topics

Appendix F. Preprocessor

Appendix G. ATM Case Study Code

Appendix H. UML 2: Additional Diagram Types

Appendix I. C++ Internet and Web Resources

Appendix J. Introduction to XHTML

Appendix K. XHTML Special Characters

Appendix L. Using the Visual Studio .NET Debugger

Appendix M. Using the GNU C++ Debugger


C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627 © 2008-2020.
If you may any questions please contact us: