Colorado State University

Hints for Using C++



C++ Compilers

g++: The GNU C++ compiler

xlC: C++ compiler

CC: C++ compiler

Read the man pages for each compiler to determine the various compiler flags (e.g. -g for inserting debugging symbols) and allowable file extensions


Compiling a Program in a Single File

Compiling a program in a single file simply involves giving the compiler the filename of a C++ source program:
        g++ reverse1.cc
This command compiles the program reverse1.cc and puts the object code into the file named a.out

Consider the program for this example, reverse1.cc:
  // a simple program to illustrate compiling.
  #include   
  #define MAX  5   // The maximum number of numbers we can input.
  
  //  Function reverse reverses inarray and places the result in revarray.
  void reverse(int inarray[], int revarray[]){
  
  int j;
    for (j=0;j<MAX;j++){
      revarray[j] = inarray[MAX - j -1];
    }
  }
  
  void main(){
  
  int i;
  int inarray[MAX];            // The input array
  int revarray[MAX];           // The reversed array
  
  cout<<"Enter 5 integers each followed by <return>" << endl;
  for (i=0;i<MAX;i++){
    cin >> inarray[i] ;           // Get the five numbers.
  }
  
  reverse(inarray,revarray);     // Call our reverse function.
  
  cout << "The integers you input are: " << endl;
  
  for (i=0;i<MAX;i++){          // print out inarray
    cout << inarray[i] << " ";
  }
  
  cout << endl;
  
  cout << "The integers in reverse order are: " << endl;
  
  for (i = 0;i<MAX; i++){       // print out revarray.
    cout << revarray[i] << " " ;
  }
  
  cout << endl;
  }


Compiling with Multiple Files

Compiling with multiple files involves a little more work

We can compile the files separately into object files with the -c compiler option and then use the compiler to link them together and put them in a file named a.out
g++ -c revlib.c Make the first object file
g++ -c rev2.cc Make the second object file
g++ rev2.o revlib.o   Now link them into an executable
As programs get larger and involve more files this method becomes cumbersome

Makefiles: An alternative method is to use a makefile
After creating a file called makefile (or Makefile) in the same directory as the source files, one invokes the make program by typing
       make
Make is initially discussed in CS 200 and later in CS 314

Example makefile:
  rev2: rev2.o revlib.o
          g++ -o rev2 rev2.o revlib.o
  
  rev2.o: rev2.cc
          g++ -c rev2.cc
  
  revlib.o: revlib.cc revlib.h
          g++ -c revlib.cc
  
  clean:
          rm rev*.o *~
Note: The indented lines in any makefile must begin with a tab character; if the first character of an indented line is a space, an error message is returned whenever the makefile is used

rev2.cc: The main file of a sample program with multiple files
  // A simple program to illustrate how to link multiple files together.
  # include 
  # include "revlib.h"   
  
  void main(){
  
  int i;
  int inarray[MAX];            // The input array
  int revarray[MAX];           // The reversed array.
  
  cout<<"Enter 5 integers each followed by " << endl;
  for (i=0;i<MAX;i++){
    cin >> inarray[i] ;       // Get the input from stdin
  }
  
  reverse(inarray,revarray);  // Reverse the input array.
  
  cout << "The integers you input are: " << endl;
  
  for (i=0;i<MAX;i++){       // Print inarray
    cout << inarray[i] << " ";
  }
  
  cout << endl;
  
  cout << "The integers in reverse order are: " << endl;
  
  for (i = 0;i<MAX; i++){    // Print revarray
    cout << revarray[i] << " " ;
  }
  
  cout << endl;
  }

revlib.h: A header file for this sample program
  #ifndef __REVLIB_H__
  #define __REVLIB_H__
  #define MAX 5
  
  void reverse(int inarray[],int revarray[]);
  #endif

revlib.cc: Another file for the sample program
  // A simple library file to reverse an array and place it in another array.
  #ifndef __REVLIB_CC__
  #define __REVLIB_CC__
  
  #include "revlib.h"
  
  void reverse(int inarray[], int revarray[]){
  // We assume the caller is taking care of matching the size of revarray 
  // and inarray!
  int j;
  
    for (j=0;j<MAX;j++){
      revarray[j] = inarray[MAX - j -1];
    }
  }
  #endif


More C++: Templates

Templates allow one to write generic classes functions in C++. For example, instead of writing a separate stack class for integers, floats, and doubles, one can write a generic stack and then instantiate a stack<float>, stack<double> or stack<int> whenever one wants.

Unfortunately, templates are one of the newer features of C++; so, while the syntax is well defined in the language definition, the actual method of implementation is not specified and varies between compilers. What concerns us here is how to write template modules and make them work with each compiler.

The problem

Suppose we have three files: where stack.h contains the class definition for template class, stack, and stack.cc contains the member functions for the class stack. When main.cc is being compiled, it knows it can make a stack<double> because the function prototypes are included from stack.h, but it doesn't know how to build the member functions because the code is in another file, stack.cc. Similarly, when stack.cc is compiled, it knows how to build any member function, but as far as it can tell, no one has asked for one to be built. Currently, each compiler has different work arounds for this problem.

One Solution

One solution that always works is to include the member functions found in stack.cc in the stack.h file. Since the #include directive just glues the text of stack.h into main.cc, this solves the problems of compiling separate files. The disadvantage of this method is that compilation will take longer since one is effectively compiling three files even if one only makes minor changes to one of them, say, main.cc. On a program of significant size this compromise might be unacceptable.

The HP CC compiler

The CC compiler currently requires a fake instantiation of each needed template type in the files that contain member functions. For example, suppose we want to instantiate a stack<float> in main.C. We need to add
      stack<float> FakeStack;
to the end of the stack.C file. Once a stack<float> is built when stack.C is compiled, the member functions are available to other instantiations in main.C. Obviously this is a workaround since it doesn't really allow general purpose library code, but maybe the problem will go away, ... someday.

So, we are left with only the CC compiler (running only on HPs) to use when we do separate compilation.




Copyright © 1998: Colorado State University, CS Department. All rights reserved.