Using Header and Source Files

In C++, it's common practice to divide your source code into header and source files. You place the class declarations in the header files and place the definitions of the member functions in the source files. Header files usually have the suffix .H and source files have the suffix .CPP. For example, here's the header file for the Date class:

// DATE.H

#if !defined( _DATE_H_ )

#define _DATE_H_

class Date

{

Date();

int getMonth() const;

// ...

};

inline Date::getMonth() const

{

return month;

}

// etc...

#endif // _DATE_H_

Notice that this header file contains the definitions for inline member functions. The compiler must have access to the source code of an inline function in order to insert the code each time the function is called.

Also note that the header file uses the #if preprocessor directive and the defined preprocessor operator for conditional compilation. This prevents multiple inclusion of header files in a multimodule program.

Here's the source file for the Date class:

// DATE.CPP

#include "date.h"

Date::Date()

{

// ...

}

// etc...

Note that the source file includes its corresponding header file.

In general, you should use one header file and one source file for each class unless you are writing very small classes, or classes that are very closely related and should always be used together.

Roughly speaking, a header file describe a class's interface and a source file describes its implementation. This distinction is important when your classes may be used by other programmers. To use the Date class, for example, other programmers would simply include the header file DATE.H in their source files. Those programmers don't need to see how the member functions are implemented; all they need to see are the prototypes of the member functions. As long as they can link with DATE.OBJ when linking their program, they don't need to see DATE.CPP. If you rewrite DATE.CPP, you can simply recompile it to produce a new DATE.OBJ file; the other programmers don't need to change their code.

Unfortunately, it's necessary that some aspects of a class's implementation be revealed in the header file. The private members of a class are visible in the header file, even though they aren't accessible. Furthermore, if your class has inline member functions, their implementation is also visible. If you change the private members or inline functions of your class, those changes are reflected in the header file, and all the programmers who use that class must recompile their code with the new header file. However, they still don't have to rewrite any of their code, as long as the class's interface hasn't changed—that is, as long as you haven't changed the prototypes of the public member functions.

You should also consider whether your #include statements need to be in
your header file or your source file. For example, if one of your class's
member functions takes a time_t structure as a parameter, you have to place
#include "time.h" in the header file. On the other hand, if the time_t
structure is used only in the internal computations of a member function, and is not visible to someone calling the function, then you should place
#include "time.h" in the source file instead. In the first case, the interface
requires TIME.H, and in the second case, the implementation requires it.
Don't place #include statements in your header files if placing them in the
source file suffices.

By separating a class's interface and implementation, you make your classes as self-contained as possible, so they don't depend on each other's implementation details. This practice follows the principle of encapsulation, which is discussed in more detail in Chapter 9, “Fundamentals of Object-Oriented Design.”