SEPARATE COMPILATION

Separate compilation is available with C++ and it follows the identical rules as given for ANSI-C separate compilation. As expected, separately compiled files can be linked together. However, since classes are used to define objects, the nature of C++ separate compilation is considerably different from that used for ANSI-C. This is because the classes used to create the objects are not considered as external variables, but as included classes. This makes the overall program look different from a pure ANSI-C program. Your programs will take on a different appearance as you gain experience in C++.

ANOTHER PRACTICAL EXAMPLE

Once again we come to the practical part of this lesson where we study a practical class that can actually be used in a program but is still simple enough for the student to completely understand.

In the last chapter we studied the date class and in this chapter we will study a simple time class. You should begin by studying the file named TIME.H which will look very similar to the date class header. The only major difference in this class from the date class is the overloaded constructors and methods. The program is a very practical example that illustrates very graphically that many constructor overloading are possible. The header file time.h uses #ifndef and #define directives to define the class as time_of_day.

// time.h

// This is probably the minimum usable time class, but is intended as
// an illustration of a class rather than to build an all inclusive
// class for future use. Each student can develop his own to suit
// his own taste.

#ifndef TIME_H
#define TIME_H

class time_of_day {
protected:
int hour; // 0 through 23
int minute; // 0 through 59
int second; // 0 through 59
static char format; // Format to use for output
static char out_string[25]; // Format output area

public:
// Constructor - Set time to current time and format to 1
time_of_day(void);
time_of_day(int H) {hour = H; minute = 0; second = 0; };
time_of_day(int H, int M) {hour = H; minute = M; second = 0; };
time_of_day(int H, int M, int S) {hour = H;
minute = M; second = S; };

// Set the time to these input values
// return = 0 ---> data is valid
// return = 1 ---> something is out of range
int set_time(void);
int set_time(int hour_in);
int set_time(int hour_in, int minute_in);
int set_time(int hour_in, int minute_in, int second_in);

// Select string output format
void set_time_format(int format_in) { format = format_in; };

// Return an ASCII-Z string depending on the stored format
// format = 1 13:23:12
// format = 2 13:23
// format = 3 1:23 PM
char *get_time_string(void);
};
#endif

The implementation for the time class is given in the file named TIME.CPP.

// time.cpp

#include <stdio.h> // For the sprintf function
#include <time.h> // For the time & localtime functions
#include "time.h" // For the class header

char time_of_day::format; // This defines the static data member
char time_of_day::out_string[25]; // This defines the string

// Constructor - Set time to current time
// and format to 1
time_of_day::time_of_day(void)
{
time_t time_date;
struct tm *current_time;

time_date = time(NULL);
current_time = localtime(&time_date);
hour = current_time->tm_hour;
minute = current_time->tm_min;
second = current_time->tm_sec;

format = 1;
}

// Set the time to these input values
// return = 0 ---> data is valid
// return = 1 ---> something out of range
int time_of_day::set_time(void) {return set_time(0, 0, 0); };
int time_of_day::set_time(int H) {return set_time(H, 0, 0); };
int time_of_day::set_time(int H, int M) {return set_time(H, M, 0); };
int time_of_day::set_time(int hour_in, int minute_in, int second_in)
{
int error = 0;

if (hour_in < 0) {
hour_in = 0;
error = 1;
} else if (hour_in > 59) {
hour_in = 59;
error = 1;
}
hour = hour_in;

if (minute_in < 0) {
minute_in = 0;
error = 1;
} else if (minute_in > 59) {
minute_in = 59;
error = 1;
}
minute = minute_in;

if (second_in < 0) {
second_in = 0;
error = 1;
} else if (second_in > 59) {
second_in = 59;
error = 1;
}
second = second_in;

return error;
}

// Return an ASCII-Z string depending on the stored format
// format = 1 13:23:12
// format = 2 13:23
// format = 3 1:23 PM
char *time_of_day::get_time_string(void)
{
switch (format) {
case 2 : sprintf(out_string, "%2d:%02d", hour, minute);
break;

case 3 : if (hour == 0)
sprintf(out_string, "12:%02d AM", minute);
else if (hour < 12)
sprintf(out_string, "%2d:%02d AM", hour, minute);
else if (hour == 12)
sprintf(out_string, "12:%02d PM", minute);
else
sprintf(out_string, "%2d:%02d PM",
hour - 12, minute);
break;

case 1 : // Fall through to default so the default is also 1
default : sprintf(out_string, "%2d:%02d:%02d",
hour, minute, second);
break;
}

return out_string;
}

Once again, the code is very simple and you should have no problem understanding this example in its entirety. It should be pointed out that three of the four overloadings actually call the fourth so that the code did not have to be repeated four times. This is a perfectly good coding practice and illustrates that other member functions can be called from within the implementation.

The example program named USETIME.CPP is a very simple program that uses the time class in a very rudimentary way as an illustration for you.

// usetime.cpp

#include <iostream.h>
#include "date.h"
#include "time.h"

void main(void)
{
date today;
time_of_day now, lunch(12, 15);

cout << "This program executed on " << today.get_date_string() <<
" at " << now.get_time_string() << "\n";

cout << "We are planning lunch at " << lunch.get_time_string() <<
" tomorrow.\n";

lunch.set_time(13);
cout << "We decided to move lunch to "<< lunch.get_time_string()
<< " due to a late meeting.\n";
}

// Result of execution
// This program executed on Jan 20, 1991 at 10:34:16
// We are planning lunch at 12:15:00 tomorrow.
// We decided to move lunch to 13:00:00 due to a late meeting.

You should be able to understand this program in a very short time. It will be to your advantage to completely understand the practical example programs given at the end of the last chapter and the end of this chapter. As mentioned above, we will use the time class and the date class as the basis for both single and multiple inheritance in the next three chapters.

WHAT SHOULD BE THE NEXT STEP?

At this point you have learned enough C++ to write meaningful programs and it would be to your advantage to stop studying and begin using the knowledge you have gained. Because C++ is an extension to ANSI-C, it can be learned in smaller pieces than would be required if you are learning a completely new language. You have learned enough to study and completely understand the example program given in chapter 12, the Flyaway adventure game. You should begin studying this program now.

One of your biggest problems is learning to think in terms of object oriented programming. It is not a trivial problem if you have been programming in procedural languages for any significant length of time. However, it can be learned by experience, so you should begin trying to think in terms of classes and objects immediately. Your first project should use only a small number of objects and the remainder of code can be completed in standard procedural programming techniques. As you gain experience, you will write more of the code for any given project using classes and objects but every project will eventually be completed in procedural code.

After you have programmed for a while using the techniques covered up to this point in the tutorial, you can continue on to the next few chapters which will discuss inheritance and virtual functions.