CS253: Software Development with C++

Fall 2019

Separate Compilation

Show Lecture.SeparateCompilation as a slide show.

CS253 Separate Compilation

Separation, by Edvard Munch

Separate Compilation

It’s often useful to separate the class interface (*.h) from the class implementation (*.cc).

Example

Foo.h Foo.cc
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED

#include <iostream>

class Foo {
  public:
    Foo();
    int get_data() const;
  private:
    double data;
};

std::ostream & operator<<(std::ostream &,
			  const Foo &);

#endif /* FOO_H_INCLUDED */
#include "Foo.h"

using namespace std;

Foo::Foo() : data(42.0) {
}

int Foo::get_data() const {
    return data;
}

ostream &operator<<(ostream &os,
		    const Foo &f) {
    return os << f.get_data();
}

Contents

The *.h file only contains the method declarations (signatures), function declarations (for non-member functions & operators) and declarations of data members. The *.cc file contains the actual code for the methods and functions. Neither one contains main.

Why?

Typing

“But it’s more typing!”

If you’re afraid of typing, then you have certainly chosen the wrong profession, and the wrong century to live in.

Compilation

Compile the code like this:

    g++ -Wall main.cc Foo.cc

If you do this with a Makefile, make sure to have main.cc also depend upon Foo.h. After all, if you change Foo.h (say, by adding a member variable) then you must recompile main.cc, because the size of Foo has changed.

Beware

Do not compile the *.h file, unless you really know what you’re doing. That will result in a *.gch (compiled header) file, which will cause no end of trouble. Remove it if you ever find it.

Example

Consider this simple program. It gets π from a header file:

    % cat main.cc
    #include "pi.h"
    #include <iostream>
    int main() {
        std::cout << pi << '\n';
        return 0;
    }
    % cat pi.h
    constexpr auto pi = 3.14;
    % g++ -Wall main.cc
    % ./a.out
    3.14
    % ls
    a.out  main.cc  pi.h

Note that pi.h is not mentioned in the compile command.

What if we try to compile pi.h?

    % g++ -Wall main.cc pi.h
    % ls
    a.out  main.cc  pi.h  pi.h.gch
    % ./a.out
    3.14
Let’s improve the value of π:
    % echo "constexpr auto pi = 3.14159;" >pi.h
    % g++ -Wall main.cc 
    % ./a.out
    3.14
Hey, why didn’t it work?
    % rm pi.h.gch 
    % g++ -Wall main.cc 
    % ./a.out
    3.14159

Moral of the story