CS 70

Should a Source File Include Its Own Header File?

  • Duck speaking

    Should a source file include its own header file?

  • LHS Cow speaking

    Hmm. Good question. What do you think?

In the cowchat/cowmath example, should printmoos.cpp #include printmoos.hpp?

In fact, either answer can be considered correct! That's because, in this particular example, they are both reasonable.

Technically, printmoos.cpp does not need #include "printmoos.hpp" because it does not require a forward declaration of the function printMoos. The function definition given in printmoos.cpp also serves as a declaration.

On the other hand, it is a good idea in general for source files to include their own header files.

An Example

To see why a source file might need to include its own header, consider this file:

moobaa.cpp:

void printMooBaa(int n) {
    printMoo(n);
}

void printMoo(int n) {
    if (n > 0) {
        std::cout << "Moo! " << endl;
        printBaa(n);
    }
}

void printBaa(int n) {
    if (n > 0) {
        std::cout << "Baa! " << endl;
        printMoo(n - 1);
    }
}

Do you see the problem?

Why won't moobaa.cpp compile?

Imagine you are the compiler. You are going through this code line by line… what happens?

First, printMooBaa calls printMoo, but printMoo hasn't been declared yet! Then, printMoo calls printBaa, but printBaa also hasn't been declared yet.

The solution: forward declaration! We can add a header file,

moobaa.hpp:

#ifndef MOOBAA_INCLUDED
#define MOOBAA_INCLUDED

void printMooBaa(int n);
void printMoo(int n);
void printBaa(int n);

#endif

and #include our new header file in our code file,

moobaa.cpp:

#include "moobaa.hpp"

void printMooBaa(int n) {
...

Now all our functions have been declared before they're used: our code will compile!

Upshot

In general, it is best practice for a .cpp file to #include its own .hpp file so functions get forward declared.

  • Duck speaking

    But, like, how often am I really going to have some complicated recursion like that?

  • LHS Cow speaking

    True. But even when there is an order that would declare everything, do you always want to spend time figuring it out?

  • RHS Cow speaking

    For that matter, is that necessarily how you want to organize your code?

  • LHS Cow speaking

    So, it's not always strictly necessary for a source file to include its own header file…

  • RHS Cow speaking

    But it is usually a good idea. At the very least it frees you from worrying about the order of your functions!

  • LHS Cow speaking

    Okay, that's another chunk done. Head up to the parent page to see your progress and take a break if you need it!

(When logged in, completion status appears here.)