About the Author:

3.13 Separate Compilation

C++ supports separate compilation, where pieces of the program can be compiled independently through the two stage approach of compilation and then linking, so changes to one class would not necessarily require the re-compilation of the other classes. The compiled pieces of code ( .o or .obj files)[8] are combined through the use of the linker (in the use of Borland C++ it is ilink32.exe). Separate compilation allows programs to be compiled and tested one class at a time, even built into libraries for later use. It is therefore good practice to place each class in a separate source file to take full advantage of separate compilation with the C++ language.

The source code for each class is stored in two files:

A source file (.cpp) - the implementation of the methods.

A header file (.h) - the definition of the class.

The header file contains the declarations for the methods contained in the cpp file, allowing for these cpp files to be compiled into libraries. The cpp file will define the methods and by including the header file within the cpp file you will ensure consistency between the declarations and definitions.

So the Account class would take the form of three separate files:

Account.h - That stores the class declaration and definition.

Account.cpp - That stores the method definitions for that class.

Application.cpp - That stores the application, i.e. the main() method for the application.

You should not place using directives in header files where possible. If we were to use using namespace std; in our header file, all cpp files that include this header would also include this using directive. This would have the effect of turning off namespaces in your project (in this case for std only).

To compile the application, you must now specify the files to be used in the compilation. So, to compile all the files at once use: bcc32 Application.cpp Account.cpp, where one of the source files contains a main() method. This can be seen in Figure 3.11, “Compilation, and the output from the Separately Compiled Example.”.

Figure 3.11. Compilation, and the output from the Separately Compiled Example.

Just before we continue we need to briefly discuss preprocessor directives. Preprocessor directives are orders for the preprocessor, not for the program itself. They must be specified in a single line of code and should not end with a ; (semicolon). Some preprocessor directives are: #include (insert a header file here), #define (define a constant macro)

#define PI 3.14

#undef (removes definition), #if, #ifdef, #ifndef, #endif, #else, #elif (control directives to remove part of a program depending on the condition),

#ifndef MAX_WIDTH
#define MAX_WIDTH 1000
#endif

#line (allows control over compile time error messages), #error (allows us to abort compilation if required), e.g.

#ifndef __cplusplus
#error You need a C++ compiler for this code!
#endif

and #pragma (used for compiler options specific to a particular platform and compiler).

If there are multiple classes, some of which use the same parent, you can use compiler directives to prevent the re-definition of the same class, which would result in a compiler error. These directives can be placed around the class definition such as:

In this case, the compiler directives simply state that if the CurrentAccount class is already defined then do not redefine it. This is determined by the currentAccount_hvalue, that if undefined is simply defined, and so used as a flag. This process is to ensure that we have not broken the C++ single definition rule: You can declare anything as many times as you want, but you can only define it once.

Here is an example of the complexities that arise with separate compilation. In this example A is the parent of AA and B. AA is a child of A and B is a part-of AA. B is a child of A and AA is a part-of B. I have added the minimum namespace usage necessary in the header files: testapp.cppA.hA.cppAA.hAA.cppB.hB.cpp

Fortunately, for the purpose of professional development, tools such as Integrated Development Environments(IDEs) can automatically insert the required preprocessor directives.

[8] The .o or .obj filename extensions are called object files, but importantly this has nothing to do with object, as in object-oriented, rather it simply means object, as in goal or aim.