C++ Header Files
Jess
Posted on December 12, 2020
In C++, functions and variables need to be declared before they can be used. For example, if you want to call a function in main
, the function needs to be before main
in your source code so the compiler knows about it, because functions are compiled in the order in which they appear.
#include <iostream>
#include <ctime>
int getRandomTotal()
{
return rand() % 10 + 1;
}
void printHelloWorld()
{
int total = getRandomTotal();
std::cout << "Print " << total << " times:\n\n";
for (int i = 0; i < total; i++)
{
std::cout << "Hello World!\n";
}
}
int main()
{
srand(time(NULL));
printHelloWorld();
return 0;
}
Here printHelloWorld
is called in main
, so it needs to be before it. getRandomTotal
is called in printHelloWorld
and therefore needs to be before that function.
This isn't exactly convenient and can get pretty messy fast. Fortunately, you can use a function prototype instead, and then the function can exist below the function call, or in an entirely different file.
The function prototype is the heading of a function, which consists of the return type, function name, and parameters, followed by a semi-colon:
functionType functionName(parameter list);
You don't have to specify the variable names for the parameter list in the function prototype but you have to specify the data type.
For example:
#include <iostream>
int addNumbers(int, int); // function prototype
int main()
{
std::cout << addNumbers(2, 3) << std::endl;
return 0;
}
int addNumbers(int x, int y)
{
return x + y;
}
Here is the same program re-written with function prototypes:
// Function prototypes
void printHelloWorld();
int getRandomTotal();
int main()
{
srand(time(NULL));
printHelloWorld();
return 0;
}
void printHelloWorld()
{
int total = getRandomTotal();
std::cout << "Print " << total << " times:\n\n";
for (int i = 0; i < total; i++)
{
std::cout << "Hello World!\n";
}
}
int getRandomTotal()
{
return rand() % 10 + 1;
}
Now, the function prototypes are at the top, and the function definitions are below main
.
You can see that the order of the functions no longer matters. I rearranged the functions (putting getRandomTotal
below printHelloWorld
) to illustrate that it still works. This is because the compiler knows about both functions before printHelloWorld
is called in main
.
However, because each file is compiled independently, if I split the function definitions into another file the order that the definitions are in matters again:
// file main.cpp
#include <iostream>
#include <ctime>
// Function prototypes
void printHelloWorld();
int getRandomTotal();
int main()
{
srand(time(NULL));
printHelloWorld();
return 0;
}
// file funcs.cpp
#include <iostream>
#include <ctime>
void printHelloWorld()
{
int total = getRandomTotal();
std::cout << "Print " << total << " times:\n\n";
for (int i = 0; i < total; i++)
{
std::cout << "Hello World!\n";
}
}
int getRandomTotal()
{
return rand() % 10 + 1;
}
This results in the error 'getRandomTotal': identifier not found
If, in funcs.cpp
, you put getRandomTotal
before printHelloWorld
it will work again.
Header Files
In C++, header files are used to contain function declarations. If you wanted to use printHelloWorld
and getRandomTotal
in multiple files you would have to include the function prototypes every time, the same way you need to include files like iostream
. Instead, you can place the declarations in a header file and include that. That is what you're doing when you use #include <iostream>
.
Header files end in .h
or .hpp
. When I use Visual Studio it creates header files with the .h
extension, and when I use Xcode it creates them with .hpp
. I believe .h
is a C thing, but is used frequently in C++ programs, and .hpp
is a C++ thing but can't be used in C programs. Whichever you use in your C++ program, be consistent.
// file main.cpp
#include <iostream>
#include <ctime>
#include "Funcs.h" // <- our header file
int main()
{
srand(time(NULL));
printHelloWorld();
std::cout << addNumbers(2, 3) << std::endl;
return 0;
}
// file Funcs.h
// Function declarations
#pragma once
int getRandomTotal();
void printHelloWorld();
// file Funcs.cpp
// Function definitions
#include <iostream>
#include <ctime>
int getRandomTotal()
{
return rand() % 10 + 1;
}
void printHelloWorld()
{
int total = getRandomTotal();
std::cout << "Print " << total << " times:\n\n";
for (int i = 0; i < total; i++)
{
std::cout << "Hello World!\n";
}
}
Brackets vs Quotes
The compiler looks for header files in several locations. If you include your header file in quotes, the compiler will first look in the same directory as your source file before looking in other directories. If you use brackets, the compiler does not look in the same directory as your source file.
Quotes can be used for everything and the compiler will find it. Files in quotes are relative to the current file. If I created a folder called Headers
and moved Funcs.h
inside it, I could write:
#include "./Headers/Funcs.h"
but #include "Funcs.h"
will still work as well.
Include Guards
To prevent files from being inserted multiple times and causing errors, include guards are used.
You might see #pragma once
, as I've used above.
Another one is:
// file Funcs2.h
#ifndef Funcs2_h
#define Funcs2_h
int multiplyNums(int, int);
#endif
// file Funcs2.cpp
#include "Funcs2.h"
int multiplyNums(int x, int y)
{
return x * y;
}
// file main.cpp
#include "Funcs2.h"
int main()
{
std::cout << multiplyNums(12, 3) << std::endl;
return 0;
}
Again, just be consistent in what you use.
What Not to Put in a Header File
Including these in a header file are either not allowed, or considered bad practice:
- built-in type definitions at namespace or global scope
- non-inline function definitions
- non-const variable definitions
- aggregate definitions
- unnamed namespaces
- using directives
Further Reading / References
- C++ All-in-One for Dummies, 3rd Ed by John Paul Mueller and Jeff Cogswell
- Header Files - Microsoft Docs
- C++ Header Files - The Cherno (video)
Posted on December 12, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.