Don't like this style? Click here to change it! blue.css

Class 8: Makefiles, Templates, Class Headers

I've allocated the first 9 lectures of this course to learning C++ inside and out. The larger section is behind by one lecture, so this set of notes is probably the last we'll get to before moving into the heart of Data Structures.

With that in mind, Makefiles and Templates are topics which everyone putting C++ on a resume should know about.

GNU make

This (make) is a tool to help automate your build process. I want to demonstrate it to you for several reasons.

Compile Task 1: Go and make a workspace out of cisc220/more-modules. Build main.cpp in the traditional way.

Object Task 2: Now follow the instructions in the readme to create 4 object files (main.o, teacher.o, student.o, monk.o) then build those object files into an executable.

Delta Task 3: This one is subtle. Change student.cpp to have a different message. Now ONLY recompile student g++ -c student.cpp. Now build the_world like this: g++ *.o -o the_world and run it.

XKCD compiling

So that one was a bit nutty. Here is what happens. Each one of your files was compiled into an objectfile, and then those get linked together into an executable. So if you think in this way you can add a change you make to your project without having to recompile everything. (Notice, we didn't compile anything other that student.cpp.) This allows the above comic to be invalid for your employees (you will have employees that compile one day, right?).

Make Task 4: Now run make, then ./the_world.

Not bad right?

Adjust Task 5: Adjust teacher.cpp to a new message. Run make then ./the_world.

Touch Task 6: Now type touch monk.cpp followed by make.

make keeps track of when a file has been altered. In this case our makefile does some deliberate creation of object files. touch is a *nix command for adjusting a files last modification date. It pretends to "update" a file. So when we touched the monk make thought we needed to rebuild the monk.

Clean Task 7: Now type make clean. What happened?

Making your makefile

So Makefiles are really just a systemic way of organizing your build process. The basic format is this:

        
          TARGET : PREREQS
          \tRECIPE LINE
          \tRECIPE LINE
        
      

This is one of the odd places where you actually need a tab character. As recipe lines are recognized by the leading tab.

So a super simple Makefile might look like:

        
      all:
        g++ main.cpp monk.cpp student.cpp teacher.cpp
        
      

In that case, calling make just calls that one simple line. Not a huge benefit other than saving some typing.

Evaluation Task 8: So what would do you think happens when our Makefile got called? What about make clean?

Advanced Usage: There are some awesome Makefiles out there that make really complicated builds work like a charm. I would encourage you to spend some time looking at the documentation and a tutorial or two.

Or even this monster:

Class Headers

Let's use this monk/teacher/student example to move onto the next topic: classes with headers.

I've had many students ask me the "proper" way of using headers with classes. Like always there are many right ways and there are wrong ways.

The truth is that the entire header file will be copied into anything which includes it. The next simple truth is that a function can be used in three ways:

  1. To declare the function for later (return type and input types)
  2. To define the function (braces and code after the declaration)
  3. To call the function (called with parentheses and possibly inputs)

So a good convention is to have headers declare things, have *.cpp files define them, and other functions call them.

For classes, nothing really changes. Declare the methods and attributes and whether they are public or private in the header. Then define the functions in a blah.cpp file.

Speak Task 9: For each of our three person types add a function void speak(); both to the header files and the definition in the CPP files. Have the three types speak something appropriate for who they are. Call all three speak methods in main.cpp.

Templates

The notes have templates in them but we glanced over them quickly. We might run out of time here too, but they are still very important to any C++ coders.

A template allows you to run a generic program, without having to specify the input type. Let's do an example:

Generic Task 10: Write a speak function which uses a template. Use your function to have each different person in main.cpp speak their own language.