Avatar ·

*.h или *.hpp для заголовочных файлов C++: какое расширение выбрать?

Всем привет! Я новичок в C++ и разрабатываю свой первый небольшой проект — класс для работы с матрицами. Я заметил, что в разных проектах и учебниках используются разные расширения для заголовочных файлов: одни пишут `matrix.h`, другие — `matrix.hpp`. У меня возникла путаница. Я привык, что в C все заголовочные файлы имеют расширение `.h`. Но C++ — это отдельный язык, хоть и во многом основанный на C. Когда я пишу определение класса, например: ```cpp // matrix.h #ifndef MATRIX_H #define MATRIX_H class Matrix { public: Matrix(int rows, int cols); void print() const; private: int rows_, cols_; double* data_; }; #endif ``` ...мне кажется логичным использовать `.hpp`, чтобы явно указать, что это C++, а не C. Но некоторые коллеги говорят, что `.h` — это стандарт, и `.hpp` только путает. Другие утверждают, что `.hpp` — это признак "настоящего" C++ кода. Подскажите, пожалуйста, какое расширение правильнее использовать в современном C++? Есть ли объективные причины выбирать одно перед другим? Или это просто вопрос личных предпочтений и стиля кодирования? Мне важно понять, чтобы в будущем не выглядеть непрофессионально и придерживаться единого стандарта в своих проектах. <<>>

Краткий ответ

Строгих правил нет — это вопрос соглашений и контекста. Однако в сообществе C++ сложились определённые практики, которые помогут вам сделать осознанный выбор.

Подробное объяснение

Расширение файла не влияет на компиляцию, если вы явно указываете компилятору тип файла (например, -x c++). Но для человека и инструментов (IDE, линтеры, системы сборки) расширение — важный сигнал.

Когда использовать .h

  • Гибридные проекты C/C++. Если ваш проект содержит код на C и C++, .h — нейтральный выбор. Он не вводит в заблуждение C-разработчиков.
  • Библиотеки с C-совместимым API. Например, многие системные заголовки (POSIX, WinAPI) используют .h, даже если внутри есть C++-конструкции.
  • Исторические проекты. Если вы работаете с кодовой базой, где устоялось .h, лучше придерживаться её стиля.

Когда использовать .hpp

  • Чистые C++ проекты. .hpp явно говорит: "Это C++, не пытайтесь скомпилировать как C". Это снижает риск случайного включения в C-код.
  • Шаблонные классы и инлайн-функции. В C++ заголовки часто содержат реализации (шаблоны, constexpr). .hpp подчёркивает, что файл не просто объявление.
  • Современные библиотеки. Boost, Qt (частично), многие новые проекты используют .hpp. Это стало неформальным стандартом для "чистого" C++.

Другие распространённые расширения

  • .hxx — альтернатива .hpp, часто в проектах, где .hpp уже занято (например, в некоторых сборках CMake).
  • .hh — редко, используется в некоторых академических проектах.
  • .inl — для инлайн-реализаций (отдельно от основного заголовка).

Практические рекомендации

Для вашего класса Matrix я бы посоветовал matrix.hpp:

// matrix.hpp
#pragma once  // современная альтернатива #ifndef

class Matrix {
public:
    Matrix(int rows, int cols);
    ~Matrix();  // не забудьте деструктор!
    void print() const;
private:
    int rows_, cols_;
    double* data_;
};

// matrix.cpp
#include "matrix.hpp"
#include <iostream>
#include <algorithm>

Matrix::Matrix(int rows, int cols) 
    : rows_(rows), cols_(cols), data_(new double[rows * cols]()) {}

Matrix::~Matrix() { delete[] data_; }

void Matrix::print() const {
    for (int i = 0; i < rows_; ++i) {
        for (int j = 0; j < cols_; ++j)
            std::cout << data_[i * cols_ + j] << " ";
        std::cout << "\n";
    }
}

Что говорят авторитетные источники

  • Google C++ Style Guide: рекомендует .h для всех заголовков, даже для C++.
  • LLVM Coding Standards: использует .h в основном, но допускает .hpp для шаблонов.
  • C++ Core Guidelines: не дают прямых указаний, но в примерах чаще встречается .h.

Вывод

Выбор между .h и .hpp — это соглашение вашей команды или проекта. Если вы работаете один — выберите то, что кажется логичным, и придерживайтесь его. Для чистого C++ проекта .hpp — более современный и информативный выбор. Если же проект смешанный или вы планируете публиковать библиотеку с C-совместимым API — остановитесь на .h.

Главное — единообразие. Не смешивайте расширения в одном проекте, иначе вы запутаете себя и других разработчиков.

<<>>

Альтернативный взгляд: забудьте о расширении, думайте о структуре

Я считаю, что дискуссия о .h vs .hpp часто отвлекает от более важных вещей. В современном C++ (C++17 и новее) гораздо важнее:

  • Использовать модули (C++20). Вместо заголовочных файлов — export module matrix;. Это решает проблему расширений раз и навсегда.
  • Правильно организовывать include-защиту. #pragma once проще и надёжнее, чем #ifndef.
  • Разделять интерфейс и реализацию. Даже в заголовочных файлах: публичные методы — в начале, приватные — в конце.

Если ваш проект использует CMake, вы можете вообще не думать о расширениях — система сборки сама определит тип файла. Например, в CMakeLists.txt:

set(SOURCES
    src/matrix.cpp
    include/matrix.h  # или .hpp — неважно
)

Мой совет: выберите .hpp для чистого C++, но не тратьте время на споры. Лучше потратьте его на написание качественного кода с правильным использованием const, noexcept, RAII и современного C++. Расширение файла — это последнее, что волнует компилятор и читателя, если код написан хорошо.