C++ Header Files

Learn what header files are, why we might want to use them, and get practice implementing them.
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

3D art showing a character in a bar
Ryan McCombe
Ryan McCombe
Posted

In a previous section, we saw how we could declare and define a function as two separate steps.

The declaration of a function includes its return type, its name, and the types of its parameters.

// A function declaration
int Add(int x, int y);

The definition includes all those things, but also includes the body, or the implementation, of the function:

// A function definition
int Add(int x, int y) {
  return x + y;
}

Test your Knowledge

What is the difference between a function declaration and definition?

We also introduced how we could do something similar with class functions. Lets imagine we have this class:

class Character {
  void TakeDamage(int Damage) {
    // Implementation
  };
};

The above code could instead be written like this:

// character.cpp
class Character {
  void TakeDamage(int Damage);
}

void Character::TakeDamage(int Damage) {
  // Implementation
}

Test your Knowledge

How can we provide a definition for this function?

class Maths {
  int Add(int x, int y);
}

This separation may have seemed like a niche quirk when first introduced. However, it is actually the most common way C++ code is written. This section will explain why.

Using Header Files in C++

It has become standard practice to split the declaration of classes into a separate file from their implementation, and then link them back together using the #include directive.

The files where the declarations live are called Header Files and they typically have a .h extension. The files were the definitions live are .cpp files, like we've been using so far.

Whilst not necessary, it is often a good idea to have one class per header file, and for each .cpp file to provide implementations for only one class:

// character.h
#pragma once
class Character {
  void TakeDamage(int Damage);
}
// character.cpp
#include "character.h"

void Character::TakeDamage(int Damage) {
  // Implementation
}

Why C++ has Header Files

The C++ community have found it much easier to work with medium-to-large scale code bases in this way. In many contexts, it is also a practical necessity.

The introduction of header files has at least two benefits:

  • It provides a summary for developers to understand what a class does. When we want to get an overview of a class, we tend to just look at its header file, as we often don't care about the low level implementation details
  • It provides a summary for other code files that need to know about a class. Rather than including the entire implementation for a class, we can just include the header file. This makes compilations faster. In a larger code base, compilation times can get extreme if the project does not use header files.

The second point is worth exploring more. It is best practice to avoid including .cpp files as much as possible, and instead prefer to #include header files.

Lets update our main.cpp to include only the header files, and not the .cpp files.

// main.cpp
#include "character.h"

int main() {
  Character PlayerCharacter;
  PlayerCharacter.TakeDamage(50);
}

Seen from the perspective of main.cpp, the fact that this code works is perhaps surprising.

It imports the character.h header file, but not the character.cpp implementation file.

Our character.h file doesn't include the character.cpp file either. So main.cpp doesn't have the contents of character.cpp, even indirectly.

Therefore, main.cpp never has the implementation of the TakeDamage function, even as it is being compiled.

But somehow, it is still able to call this function. If we check in a debugger, the call would do exactly what the function is programmed to do.

To understand how everything is working given this scenario, we will introduce the linker in the next lesson.

Test your Knowledge

What is the convention on where to create declarations and definitions?

Creating Classes in a Single Header File

Sometimes, our classes will be small enough that we do not want to split them up in this way. Our first instinct might be to tackle these classes as we have been doing so far - by just putting everything in a .cpp file.

Instead, we should put everything in a .h file. The header-only convention is much more common and useful than a "no-header" approach.

Additionally, if the class gets big enough to warrant separating into two files later, it's much easier to generate a .cpp file from a header file than it is to generate a header file from a .cpp.

This also has the benefit that, if we started with a header file, all of our #include directives would already be referencing that header file so would not need to be updated.

Defining virtual and override Functions

In previous lessons, we saw how we could add specifiers like virtual and override to our class methods.

When splitting the declaration and definition of functions into separate steps, these specifiers only need to be used with the declaration, typically in the header file.

Using these specifiers outside of a class definition will result in a compilation error.

class Character {
  virtual void FunctionA();
  virtual void FunctionB();
};

void Character::FunctionA() {

}

// No specifiers are used in the implementation
virtual void Character::FunctionB() {

}

Was this lesson useful?

Ryan McCombe
Ryan McCombe
Posted
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

The Preprocessor and the Linker
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access!

This course includes:

  • 66 Lessons
  • Over 200 Quiz Questions
  • Capstone Project
  • Regularly Updated
  • Help and FAQ
Next Lesson

The C++ Linker

Go deeper on how the linker works, and how we can take full advantage of it by using forward declarations and incomplete types.
3D art showing a character in a bar
Contact|Privacy Policy|Terms of Use
Copyright © 2023 - All Rights Reserved