In order to illustrate how the separate compilation of different pieces is done, let's look at program P84.cpp and see how we can break it in several pieces. Each piece is shown with a different color.
// This and the following 5 lines will go to the main program, main_prog.cpp
// Additional include statements should be added
// P91.cpp - This program is a driver written to demonstrate how we
can use one
// class inside another.
#include<iostream>
using namespace std;
// This part will go to ID.h file
class ID // ID class definition
{
public:
ID(
);
ID(int,
int, int);
void
display();
private:
int
left;
int
middle;
int
right;
};
// This part will go to Loan.h file
class Loan // Loan class definition
{
public:
Loan( );
Loan(ID id, double amount,
double rate, int term);
void set( );
double payment( );
void display( );
private:
ID id; //
assume an unique integer in three integer parts
double amount;
// $ amount of the loan
double rate; //
annual interest rate
int term;
// number of months, length of the loan
};
// This part will go to the main program, main_prog.cpp
int main( )
{
Loan loan1(ID(111,22,4444), 2300, 5.5, 48);
// initialize to values given
Loan loan2;
cout << "Display loan1 \n";
loan1.display();
loan2.set( ); // set the values
cout << "Display loan2 \n";
loan2.display();
return 0;
}
// This part part will go to the ID.cpp file
ID::ID( )
{
// use default values
}
ID::ID(int l, int m, int r)
{
left = l;
middle = m;
right = r;
}
void ID::display()
{
cout << right
<< "-" << middle << "-" << right << endl;
}
// This part will go to the Loan.cpp file
Loan::Loan( )
{
}
Loan::Loan(ID I, double am, double rt, int trm)
{
id = I;
amount = am;
rate = rt;
term = trm;
}
void Loan::set( )
{
int l, m, r;
ID temp_id;
// Initialize
the loan1 object
cout <<
"Enter the left part of the loan ID \n";
cin >> l;
cout <<
"Enter the middle part of the loan ID \n";
cin >> m;
cout <<
"Enter the right part of the loan ID \n";
cin >> r;
id = ID(l, m, r);
cout << "Enter
the amount of this loan \n";
cin >> amount;
cout << "Enter
the annual interest rate of this loan (in %) \n";
cin >> rate;
cout << "Enter
the term (number of months, length of the loan) \n";
cin >> term;
}
void Loan::display()
{
id.display();
cout << amount
<< endl;
cout << rate <<
endl;
cout << term <<
endl;
}
As we mentioned before, the definition of a class
will be placed in one file and the implementation of it in another file.
In the above program, we have two classes, making four files;
two .h files that keep the class definition and two .cpp files that keep
the implementation. All together we will have 5 files, 3 .cpp files and
2 .h files. Here is the list of file names:
1) main_prog.cpp
This is the main program
2) ID.cpp
This file keeps the implementation of class ID
3) ID.h
This file keeps the definition of class ID
4) Loan.cpp
This file keeps the implementation of class Loan
5) Loan.h
This file keeps the definition of class Loan
As you may expect, once you separate the files, you need to let the main function know where to get the information on each class. Likewise, when you use objects of a different class inside a class, you need to know the definition for the class that is being used. In order to do this we will use the include directive. For example, now that we have two different files for two classes, at the top of main function we need to have:
#include "ID.h"
#include "Loan.h"
(Remember that the include is a compiler directive, and so does not require a
C++ type termination with ;)
Also, we need to include the ID.h in the Loan file, because the Loan class uses the ID class. There is something you need to be aware of when you include a .h file at the top of a program: it is as if you have listed the contents of that file there. As you can imagine, if you include something twice, you will get an error. So if a .h file is already included in the Loan.h file, and then you include Loan.h and ID.h at the top of main, you seem to have the ID.h file listed twice. To fix this problem, we will somehow let the compiler know that the ID.h has been seen in Loan.h so it won't get listed again. So, for the .h file that may be listed more than once, we include a flag to avoid listing things twice. The flag has three parts, commented below with //1, //2, and //3. You do not need to include the comments in your version.
#ifndef ID_H //1
#define ID_H //2
#include<iostream>
class ID
{
public:
ID(
);
ID(int,
int, int);
void
display();
private:
int
left;
int
middle;
int
right;
};
#endif // 3
What we do is test to see whether the ID_H has been visited, or defined. If the .h file has not been defined (#ifndef ID_H), the definition following this statement is used to define the class (#define) ; If it has been defined, everything between the #ifndef ID_H and #endif is skipped. The format is the same for all other .h files, for example:
In the Loan.h file
#ifndef Loan_H //1
#define Loan_H //2
....
....
#endif // 3
Exercise 9.1
Write the above program in five different files
as described by the comments at the top of each section. Once you
have created the 5 files, include the ID.h and Loan.h file in the main.
Make sure you add the conditional compilation directives to the .h files so
they will not be visited twice.
Once you have made all these changes, compile and link all parts using
the following command:
% g++ main_prog.cpp Loan.cpp ID.cpp
This will create an a.out file that should produce
the same results as the program that had all pieces together.