CS 70

Header Files

We want both cowchat.cpp and cowmath.cpp to have a declaration of printMoos but we don't want to have to literally type it in both files.

The solution is to create a header file to contain the line that they should have in common and then use #include in both of the .cpp files to copy the header file's contents into both files before compilation.

We give our header files an extension .hpp to distingish them from source files (.cpp). Source files need to be compiled, header files need to be #included by something else, not compiled in their own right.

We will put the declaration of our printMoos function in a new header file printmoos.hpp.

printmoos.hpp:

// Header file for printMoos

void printMoos(int numMoos);

cowchat.cpp:

#include "printmoos.hpp"
#include <iostream> // for std::cin, std::cout
#include <string>   // for std::string

int main() {
    std::cout << "Chat with a cow!";
    std::string userIn;
    do {
        std::cout << std::endl  // New line
                  << "> ";      // The prompt
        std::getline(std::cin, userIn);
        int nMoos = 1 + userIn.size() % 2;
                     // ^-- Either 1 or 2 moos;
        printMoos(nMoos);
    } while (std::cin.good() && userIn != "");
    std::cout << "\n\nBye!\n";

    return 0;
}

cowmath.cpp:

#include "printmoos.hpp"
#include <iostream> // for std::cin, std::cout

int main() {
    std::cout << "Cow math!\n";

    std::cout << "Enter the first number: ";
    int x = 0;
    std::cin >> x;

    std::cout << "Enter the second number: ";
    int y = 0;
    std::cin >> y;

    if (std::cin.good()) {
        std::cout << "The cow goes: ";
        printMoos(x + y);
        std::cout << std::endl;
    } else {
        std::cout << "\n\nSomething went wrong!\n";
    }

    return 0;
}

The highlighted lines are replaced by the preprocessor with the contents of printmoos.hpp before compilation. Thus both files have a forward declaration of the printMoos function without our having to duplicate the code for that declaration!

Even better, we don't need to make any changes to printmoos.cpp, so we can use exactly the same set of compilation commands as before:

  • clang++ -c printmoos.cpp
  • clang++ -c cowchat.cpp
  • clang++ -c cowmath.cpp
  • clang++ -o cowchat cowchat.o printmoos.o
  • clang++ -o cowmath cowmath.o printmoos.o

Notice that printmoos.hpp does not appear anywhere in the compilation commands! We don't need to compile the file separately because the preprocessor adds its contents where we've used #includein cowchat.cpp and cowmath.cpp.

  • Duck speaking

    Why is it called a “header file”?

  • LHS Cow speaking

    We usually think of a function as having two parts: a header and a body. The header is the part before the first curly brace that gives the function's name, parameters, and return type. The body is the part between the curly braces, and defines the actual instructions for the function. Header files typically only contain headers, because their primary purpose is to make forward declaration easier.

  • Hedgehog speaking

    Could a header file contain other things?

  • LHS Cow speaking

    Sure! Sometimes header files declare variables, classes, and other things.

  • Dog speaking

    What about iostream in #include <iostream>? Is that a header file?

  • LHS Cow speaking

    It totally is! It declares a bunch of stuff related to input and output streams. It declares classes like std::istream and std::ostream and also variables like std::cout and std::endl.

  • Bjarne speaking

    Funny story: when the C++ standards were being created, nobody could agree on the file extension for header files. The compromise was to make header files for the standard library have no file extension at all! That's why it's iostream instead of iostream.hppor iostream.h or iostream.hxx or whatever.

  • LHS Cow speaking

    In CS 70 we will use .cpp for source files and .hpp for header files.

(When logged in, completion status appears here.)