Using multiple files

Location
  1. Courses

    /

  2. Complete C++ Course

    /

  3. The basics

    /

  4. Using multiple files

Dividing the project into multiple files

Writing all the code inside the main file is not a good thing as it will become messy very fast. It is better to separate projects into multiple files.

Types of code file

Again, in C/C++, there are two types of code file: source files and header files. In C++, the file extensions are .cpp for source files (.c in C) and .hpp or .h (.h in C) for header files. The code files that we include are the header files. We never include source files.

Header files

In the header files, we must put the function declarations, global variable declarations (We will see that later) and structure definitions. Since we only include header files, that means we always only include declarations and never definitions. That is the goal. All the compiler needs is to know that the functions exist, linking a function call to the code of the function is the linker job. If we included the definitions, the functions would be defined inside each file it is included in (Therefore, the same function would be defined many times). The linker would then fail because it would not know which function definition to link function calls to since there would be many definitions of the same function (The result would be an error in the compilation process).

Source files

The source files are where we put the definitions of the functions and global variables.

Include guards

Let us consider we have two files: file1.hpp and file2.hpp. file1.hpp includes file2.hpp and file2.hpp includes file1.hpp. Do you see the problem? They both include themselves so it creates an infinite loop. In order to avoid that, we must write a code called include guard in the header files. It is achieved by using preprocessor directives.

We must add the following preprocessor directives in each header file:

#ifndef NAME_OF_THE_FILE_HPP #define NAME_OF_THE_FILE_HPP // Here we place the code #endif

Obviously, we replace the macro name NAME_OF_THE_FILE_HPP by the name of the file. The code will be included only if it has not been included yet since once it is included one time, the macro NAME_OF_THE_FILE_HPP will be defined. We only need to write include guards in the header files, because, again, we only include header files, not source files.

#pragma once

Many people simply write the preprocessor directive #pragma once at the beginning of the header files. It acts as an include guard. However, as we saw earlier, the directive pragma is used to specify options that are compiler specific. That means that there is not guarantee that this will work with every C/++ compiler. For that reason, I recommend using the approach showed before.

A full example

math.hpp

1
2
3
4
5
6
#ifndef MATH_HPP #define MATH_HPP int pow2(int n); #endif
ame="math.cpp">
1
2
3
4
5
6
7
8
9
10
#include “math.hpp” /* The header file corresponding to the source file is often included inside the source file. That way, files included in the header file are also included in the source file. */ int pow2(int n) { return n*n; }

main.cpp

1
2
3
4
5
6
7
#include <iostream> #include “math.hpp” void main() { std::cout << pow2(5) << std::endl; }