Compiling our little program

If we were to write the program as it is in the slides, with
	thing.cxx importing:		thing.h
	holder.cxx importing: 		holder.h
	holderDriver.cxx importing:	holder.h and thing.h
we would have problems compiling it. If we tried compiling everything at once using
	g++ thing.cxx holder.cxx holderDriver.cxx
we would get an error message from the linker. Each of the files thing.cxx, holder.cxx and holderDriver.cxx can be compiled as separate pieces (and you can do that yourself, using the "-c" flag in g++), but when the linker tries to put the pieces together, it fails. Why??

The problem

The file holder.cxx does not contain a class -- just a template for a class. So if we compile holder.cxx, the compiler cannot generate the object code we need: code for operations on a holder of things. It is not until the compiler looks at holderDriver.cxx that it even sees we want a holder of things. But even then it cannot then generate object code for operations on a holder of things, because all it has when it's compiling holderDriver.cxx is that file and the ones it includes: holder.h and thing.h

Solution 1

One solution is to include in holderDriver.cxx the holder.cxx file rather than the holder.h file. This works perfectly, and is what I advise you to do in your assignment. One disadvantage of this approach is that if several .cxx files say they want to have a holder of things, each one of them causes the code for a holder of things to be compiled and incorporated into their own object code. This wastes time and space and is inappropriate in large systems. But it will do fine for our purposes.

Compiling

To compile the program, you can type:
          g++ holderDriver.cxx thing.cxx
Or you can compile it piece by piece:
          g++ -c holderDriver.cxx
          g++ -c thing.cxx
          g++ -o myprog holderDriver.o thing.o

Naming

You will notice that there is no need to compile holder.cxx. Remember, it's not a class, just a template for one. So it merely provides info to the compiler (at the moment when the compiler is producing object code for a holder of things); there is no need to compile holder.cxx itself. This means that the name holder.cxx is perhaps not a good choice. The ".cxx" implies that that a file contains code to be compiled, whereas ".h" implies that a file is just used by the compiler but not itself compiled. So we might want to rename holder.cxx holder.h. But that name is already used. A good choice (and the one you'll see in the source files) is to name it holderImp.h. The "Imp" says it's an implementation, not an interface, and the ".h" says don't compile it.

Solution 2

In a large system, Solution 1 wastes too much time and space. To avoid this, we can tell the compiler which of possibly many .cxx files that want a holder of things should be the one to contain the object code for it. Unfortunately, the details for how to do this are compiler-specific. Why? Because templates were introduced into C++ relatively late, and the standard doesn't specify enough about how they are to be implemented. That means every compiler writer has to make up his or her own way to say "this is the client code file that should contain the object code for holder of thing".

A non-problem

Note that this whole issue does not come up unless templates are involved. For example, when we compile thing.cxx, the compiler can produce all of the object code for things. Then when it sees references to thing's member functions in holderDriver, it only needs to record where the object code for thing's member functions is.

Summary of the punchline

Use solution 1: When you have a .cxx file that instantiates a template, include the file that contains the function bodies, not the file that contains the prototypes.