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 #include
d 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 #include
in cowchat.cpp
and cowmath.cpp
.
Why is it called a “header file”?
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.
Could a header file contain other things?
Sure! Sometimes header files declare variables, classes, and other things.
What about
iostream
in#include <iostream>
? Is that a header file?It totally is! It declares a bunch of stuff related to input and output streams. It declares classes like
std::istream
andstd::ostream
and also variables likestd::cout
andstd::endl
.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 ofiostream.hpp
oriostream.h
oriostream.hxx
or whatever.In CS 70 we will use
.cpp
for source files and.hpp
for header files.
(When logged in, completion status appears here.)