Question

C++ Header File Extensions: .h vs .hpp Explained

cppheadernaming-conventionsfile-type

Question

In C++, I have usually used .h files for class declarations and other header content. However, after looking through some Boost library code, I noticed that many headers use the .hpp extension instead.

What are the practical advantages and disadvantages of using .hpp instead of .h for C++ header files?

Short Answer

By the end of this page, you will understand that .h and .hpp are both header file extensions commonly used in C++, but the main difference is convention rather than language behavior. You will learn how compilers and build tools treat header files, why teams choose one extension over another, and how to pick a consistent convention for your own projects.

Concept

In C++, a header file usually contains declarations such as:

  • class declarations
  • function declarations
  • templates
  • inline functions
  • constants and macros
  • include guards or #pragma once

The key idea is this:

  • C++ itself does not require .h or .hpp
  • The file extension is mostly a naming convention
  • What matters is how the file is included and how your toolchain treats it

For example, these are both valid includes:

#include "person.h"
#include "person.hpp"

The C++ language does not assign different meaning to them. A header named person.h can contain C++ classes, templates, and namespaces. A header named person.hpp can contain the same things.

So why do both exist?

Why teams use different extensions

Historically:

  • .h has long been used for C and C++ headers
  • .hpp became popular as a way to signal "this is specifically a C++ header"

That can be useful in mixed-language codebases where both C and C++ are present.

Why this matters in real programming

The choice affects:

  • readability of the project structure
  • team consistency
  • editor and IDE behavior in some setups
  • build scripts or tooling conventions
  • whether a project wants to visually separate C headers from C++ headers

In most modern projects, the best choice is not "which extension is technically better," but rather:

  • Which convention fits the codebase?
  • Will the whole team use it consistently?

A consistent naming style reduces confusion more than the extension itself.

Mental Model

Think of .h and .hpp like two labels on the same type of folder.

  • The folder contents are what matter
  • The label helps humans understand what to expect

If you label a folder .h, people may think, "general header" or sometimes "possibly C-style header." If you label it .hpp, people may think, "this is definitely meant for C++."

The compiler, however, mostly cares about the contents and how the file is used, not the label on the folder.

Take Quiz

Syntax and Examples

A header file can use either extension.

Example using .h

// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

int add(int a, int b);

#endif
// main.cpp
#include "math_utils.h"
#include <iostream>

int add(int a, int b) {
    return a + b;
}

int main() {
    std::cout << add(2, 3) << '\n';
}

Example using .hpp

// math_utils.hpp
#ifndef MATH_UTILS_HPP
#define MATH_UTILS_HPP

int add(int a, int b);

#endif
// main.cpp
#include "math_utils.hpp"
#include <iostream>

int add(int a, int b) {
    return a + b;
}

int main() {
    std::cout << add(2, 3) << '\n';
}

What changes?

Only the filename and include string change.

The declaration, definition, compilation process, and runtime behavior stay the same.

Common convention patterns

// C-style header in mixed project
#include "logging.h"

// C++-specific header
#include "string_builder.hpp"

Some teams also use:

  • .hh
  • .hxx
  • .ipp for inline/template implementation fragments

These are conventions, not language rules.

Step by Step Execution

Consider this small example:

// user.hpp
#ifndef USER_HPP
#define USER_HPP

class User {
public:
    User(const char* name);
    const char* getName() const;

private:
    const char* name;
};

#endif
// main.cpp
#include "user.hpp"
#include <iostream>

User::User(const char* name) : name(name) {}

const char* User::getName() const {
    return name;
}

int main() {
    User user("Ava");
    std::cout << user.getName() << '\n';
}

What happens step by step

  1. main.cpp includes user.hpp
  2. The preprocessor copies the header contents into main.cpp
  3. The compiler sees the declaration of class User
  4. The compiler then sees the function definitions for User::User and User::getName
  5. In main, the program creates a User object
  6. getName() returns the stored name
  7. The program prints Ava

Important observation

If user.hpp were renamed to user.h and the include line changed to:

#include "user.h"

the program would behave exactly the same.

That is the core lesson: the extension does not change the C++ semantics.

Real World Use Cases

Here are practical situations where the choice matters.

1. Mixed C and C++ codebases

A project may have:

  • network.h for C-compatible declarations
  • serializer.hpp for C++ classes and templates

This makes the project easier to scan.

2. Library design

Some C++ libraries use .hpp to clearly signal that the headers contain:

  • templates
  • namespaces
  • classes
  • overloaded functions

This can be useful for users browsing the API.

3. Legacy systems

Older projects often use .h for everything because that has been a long-standing convention.

4. Build and tooling conventions

Some editors, code generators, or linting setups may group files by extension. A team might choose .hpp if it helps tooling recognize C++ headers more clearly.

5. Team style guides

Many teams pick one rule simply to avoid debates. That is often the most valuable benefit.

Take Quiz

Real Codebase Usage

In real projects, developers usually treat this as a style and organization decision.

Common team patterns

Pattern 1: Use .h for all headers

This is common when:

  • the codebase is entirely C++
  • the team prefers shorter names
  • there is no need to distinguish C from C++ headers

Example structure:

include/
  user.h
  order.h
  config.h
src/
  user.cpp
  order.cpp

Pattern 2: Use .h for C headers and .hpp for C++ headers

This is common when:

  • the project mixes C and C++
  • a library exposes both C and C++ APIs
  • the team wants visual separation

Example structure:

include/
  c_api.h
  cpp_wrapper.hpp

Pattern 3: Follow the existing ecosystem

If you contribute to an existing project, the normal practice is:

  • keep the current naming convention
  • avoid renaming files without a strong reason
  • prefer consistency over personal preference

Related patterns in real code

Include guards

Regardless of extension, headers should protect against multiple inclusion:

#ifndef CONFIG_HPP
#define CONFIG_HPP

struct Config {
    int port;
};

#endif

#pragma once

Many teams use this instead of include guards:

#pragma once

struct Config {
    int port;
};

Templates in headers

C++ templates are often fully defined in headers, and these may be named .hpp by convention:

// box.hpp
#pragma once

template <typename T>
class Box {
public:
    Box(T value) : value(value) {}
    T get() const { return value; }

private:
    T value;
};

Again, .h would also work technically.

Common Mistakes

1. Thinking .hpp changes compilation behavior

It usually does not.

Broken assumption:

// This is not automatically "more C++" just because of the extension.
#include "widget.hpp"

The compiler does not give special language meaning to .hpp in normal C++ source inclusion.

2. Mixing conventions randomly

Bad example:

user.h
order.hpp
config.hh
math.hxx

If there is no clear reason, this makes the codebase harder to navigate.

Better approach

Pick one convention and document it.

3. Forgetting to update includes after renaming

Broken code:

#include "person.h"

If the file was renamed to person.hpp, this include will fail.

Fixed version:

#include "person.hpp"

4. Using extension choice as a substitute for proper design

A file named .hpp is not automatically better organized.

You still need:

  • clear declarations
  • include guards or #pragma once
  • minimal includes
  • forward declarations when appropriate

5. Assuming all tools treat extensions identically

Most modern tools do, but some build scripts, syntax highlighters, or custom editors may have extension-specific rules. Always check your actual toolchain.

Comparisons

.h vs .hpp

Aspect.h.hpp
Language meaning in C++No special differenceNo special difference
Common interpretationGeneral header, sometimes C-styleC++ header
Historical usageVery commonCommon in C++ projects
Mixed C/C++ projectsCan be ambiguousHelps signal C++
BrevityShorterSlightly more explicit
Team consistency valueHigh if used consistentlyHigh if used consistently

Other related extensions

ExtensionTypical useNotes
.hGeneral headerCommon in both C and C++
.hppC++ headerConvention only
.hhC++ headerUsed by some codebases
.hxxC++ headerLess common, but valid
.ippInline/template implementationOften included from another header

Which should you choose?

SituationGood choice
Pure C++ project with existing .h filesKeep using .h
Mixed C and C++ projectConsider .h for C and .hpp for C++
Contributing to an established codebaseFollow the project convention
Starting a new team projectPick one convention and document it
Take Quiz

Cheat Sheet

Quick facts

  • .h and .hpp are both valid for C++ headers
  • The extension is mostly a convention
  • C++ does not assign different semantics to them
  • Consistency matters more than the specific choice

Common meanings

  • .h = general header
  • .hpp = C++ header

Use .hpp when

  • you want to clearly mark files as C++ headers
  • your project mixes C and C++
  • your team already uses .hpp

Use .h when

  • your codebase already uses .h
  • the project is fully C++ and there is no ambiguity
  • you prefer the shorter, traditional extension

Always remember

#include "file.h"
#include "file.hpp"

The important difference is the filename, not the C++ language behavior.

Best practice

  • choose one convention
  • apply it consistently
  • use include guards or #pragma once
  • follow the existing project style

Red flags

  • randomly mixing .h, .hpp, .hh, and .hxx
  • renaming headers without updating includes
  • assuming extension choice improves code quality by itself

FAQ

Is .hpp required for C++ headers?

No. C++ does not require .hpp. .h works as well.

Is .h only for C and .hpp only for C++?

No. That is a convention some teams use, not a language rule.

Do compilers treat .h and .hpp differently?

Usually not for included headers. The content and build configuration matter more than the extension.

Why do some libraries use .hpp?

Often to clearly signal that the header is intended for C++ and may contain classes, templates, and namespaces.

Should I rename all my .h files to .hpp?

Usually no, unless your team has a clear reason. Renaming creates churn and may break includes or tooling.

What is the best extension for a new C++ project?

There is no single best choice. Pick a convention that fits your project and use it consistently.

Can a .h file contain templates and classes?

Yes. A .h file can contain any valid C++ header content.

What matters more than the extension?

Consistency, good organization, include guards, and clear project conventions matter much more.

Take Quiz

Mini Project

Description

Create a small C++ project with a header and source file, then try the same project using both .h and .hpp. This demonstrates that the extension is a convention and helps you practice file organization, includes, and header protection.

Goal

Build a tiny class-based C++ program and verify that it works the same whether the header uses .h or .hpp.

Requirements

  • Create a header file that declares a simple class
  • Create a .cpp file that defines the class methods
  • Include the header from main.cpp
  • Add include guards or #pragma once
  • Run the program and confirm it behaves the same after renaming the header extension
Take Quiz

Keep learning

Related questions

View more