Why Multiple Files?
We always seem to make our executables in two steps. First compiling, and then linking. It seems like a pain, and I figured out I can actually it do it with just one line. Why are we making it complicated?
We'll see that it better reflects what we do when we split programs up into multiple files.
Why split things up into multiple files?
Let's see why!
An Example
Here is cowchat.cpp
, which implements a surprisingly realistic cow chatbot:
#include <iostream> // for std::cin, std::cout
#include <string> // for std::string
// 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 << ".";
}
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;
}
In the homework we usually ask you to turn on a bunch of useful compiler options. But for right now, let's strip the command line down to the bare minimum.
In order to compile cowchat.cpp
into an object file, cowchat.o
, we would run the command
clang++ -c cowchat.cpp
The -c
option tells the compiler to take the given source file and produce an object file.
In order to then produce an executable file, we would run the command
clang++ -o cowchat cowchat.o
The -o cowchat
option tells the compiler to name the output file cowchat
. Since we didn't give the -c
option, the compiler will produce an executable.
What would happen if we didn't say
-o cowchat
?As we mentioned in a previous lesson, the compiler would give the output file a default name:
a.out
Here is cowmath.cpp
, which adds two numbers, cow-style.
#include <iostream>
// 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 << ".";
}
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 minimal commands to get the cowmath
executable are
clang++ -c cowmath.cpp
clang++ -o cowmath cowmath.o
The Problem
Each of these programs might be okay by itself, but seen together as a pair of programs, they provide an example of a coding practice that is best avoided.
The Problem: Code Duplication
The problem is code duplication! The same function appears in both files.
It would be much better to just write this function once.
Copying and pasting a function from one file to another is quick and easy. Why is it so problematic?
It's because it makes code less maintainable. If you have to change something, you have to change it everywhere the same code shows up!
That's right. So what are we going to do about this?
Can we put that function in its own file and then share it with both programs?
That's exactly what we're going to do.
(When logged in, completion status appears here.)