#include
Directives
The Story So Far
With what we've learned, we can now change our original two source files into three source files, where code that's needed by both the original files is moved to its own file.
cowchat.cpp
:
#include <iostream> // for std::cin, std::cout
#include <string> // for std::string
// Declares the printMoos function.
void printMoos(int numMoos);
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 <iostream>
// Declares the printMoos function.
void printMoos(int numMoos);
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;
}
printmoos.cpp
:
#include <iostream> // for std::cin, std::cout
// Prints the given number of "moos"
void printMoos(int numMoos) {
std::cout << "Moo";
for (int i = 1; i < numMoos; ++i) {
std::cout << " moo";
}
std::cout << ".";
}
We need to run clang++
five times:
clang++ -c printmoos.cpp
compilesprintmoos.cpp
intoprintmoos.o
clang++ -c cowchat.cpp
compilescowchat.cpp
intocowchat.o
clang++ -c cowmath.cpp
compilescowmath.cpp
intocowmath.o
clang++ -o cowchat cowchat.o printmoos.o
linkscowchat.o
andprintmoos.o
to formcowchat
clang++ -o cowmath cowmath.o printmoos.o
linkscowmath.o
andprintmoos.o
to formcowmath
This is better. Less code duplication by having only one definition for
printMoos
.But there's still some code duplication: we have two declarations for
printMoos
.Right. The function declaration still appears in multiple files. If the declaration ever changes, we will have to change it everywhere!
We need a way for
cowmath.cpp
andcowchat.cpp
to share a single copy of the declaration as well! We will accomplish this with a very useful tool…
#include
Directives
As we mentioned last lesson, before the compilation process really gets started, the first step is to preprocess the code.
- The preprocessor's job is to manipulate the text in source files in various ways before they are compiled.
- You give commands to the preprocessor with preprocessor directives in your code files; these directives start with the character
#
. - The preprocessor executes one directive at a time as it passes over the file.
- After the preprocessor is finished, the modified code is passed into the compiler.
There are several preprocessor directives, but right now we will focus on a particularly important one: #include
.
#include
is essentially a kind of copy-and-paste.- It takes the entire contents of a specified file and inserts it into the including file before compiling.
#include "filename"
assumes thatfilename
is a file that we have written, and the preprocessor will look for it in the current directory.#include <filename>
assumes the file is a file that is part of the C++ system (rather than our code) and will look for it somewhere other than the current directory; typically in some system directory.
Wait a minute! I've seen
#include
before!Good catch. We've seen
#include
statements at the top of basically all of our programs so far.Ha. “Catch”.
That line finds a file named
iostream
somewhere in the standard library files and then dumps its contents right where it says#include <iostream>
.Exactly!
Um, can I ask, how do you pronounce “
#include
”?Short version:
#
is hash, so it's pronounced hash include.Long version:
#
is the “number sign” character. In many contexts in the USA, it's pronunced “pound”, but in computing contexts (and the rest of the world to avoid confusion with the£
symbol), it is usually pronounced as “hash”. That's where Twitter's “hash tags” come from, they're special tags embedded in posts, indicated with a hash sign. So on Twitter, we might say#inclusivity
as “hash-tag inclusivity”, but in C and C++ it's just “hash include”. The symbol dates back to at least the 1850s, and was included on standard typewriter keyboards in 1886. Both when C adopted it for the preprocessor (in 1972) and when first used on Twitter (in 2007), it was probably because it was a symbol on most people's keyboards that was rarely used for anything else.
You can see that we have #include <iostream>
in all three files (cowchat.cpp
, cowmath.cpp
, and printmoos.cpp
), which tells the compiler that whatever is in the iostream
file is also “in” all three of our .cpp
files.
The good news is that we didn't have to literally make three copies of that code!
Wait, that gives me an idea! Can we do the same thing with the declaration of
printMoo
??We totally can! Let's do it!
(When logged in, completion status appears here.)