.h или .hpp для заголовочных файлов C++? Разбираем раз и навсегда
Если вы когда-нибудь писали на C++ больше пары недель, то наверняка сталкивались с этим вопросом. Открываете чужой проект — там .h. Свой начинаете — в голове голос: «А может, .hpp круче?». Или наоборот: вы ярый фанат .h, а коллега утверждает, что .hpp — это единственно верный путь.
Спойлер: оба варианта технически корректны. Компилятору всё равно. Но разница есть, и она важна для организации кода, читаемости и поддержки проекта. Давайте разберёмся, что стоит за этими двумя расширениями, и когда какое выбирать.
Короткий ответ: в чём принципиальная разница?
Если совсем кратко:
.h— традиционное расширение для заголовочных файлов, пришедшее из C. Используется и в C, и в C++..hpp— более современное расширение, которое явно указывает: «Это C++, а не C». Придумано, чтобы отличать C++ заголовки от C-шных.
Но дьявол, как всегда, в деталях. Давайте копнём глубже.
Исторический контекст: откуда взялись .h и .hpp?
Язык C использовал .h для заголовков с незапамятных времён. Когда появился C++, первое время программисты просто продолжали использовать .h — и это нормально. Стандартная библиотека C++ (например, <iostream>) вообще отказалась от расширений, но это уже другая история.
Расширение .hpp появилось как ответ на потребность разделять C и C++ код. Представьте: у вас большой проект, где часть файлов на C, часть на C++. Собираете вы его, возможно, разными компиляторами или с разными флагами. Как быстро понять, какой заголовок для какого языка? Правильно — посмотреть на расширение.
Так .hpp (от «C Plus Plus header») стал де-факто стандартом в сообществе для чистых C++ заголовков, особенно в библиотеках вроде Boost.
Когда использовать .h?
Не спешите хоронить .h. У него есть свои сильные стороны:
- Совместимость с C. Если ваш заголовочный файл должен подключаться и из C, и из C++ кода — только
.h. Никаких вариантов. - Консервативные проекты. В крупных кодовых базах, где стиль сложился годами, менять расширения на
.hpp— лишняя боль. - Минимализм. Три символа вместо четырёх. Мелочь, а приятно.
Пример: заголовок, совместимый с C и C++
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
int multiply(int a, int b);
#ifdef __cplusplus
}
#endif
#endif // MATH_UTILS_H
Такой файл можно подключить и в .c, и в .cpp. Если бы вы назвали его math_utils.hpp, программист на C мог бы запутаться: «А это точно для меня?».
Когда использовать .hpp?
Здесь всё наоборот: .hpp — выбор современного C++ программиста. Особенно если:
- Вы пишете только на C++. Никакого C в проекте нет и не будет.
- Используете шаблоны, STL, исключения. Это чисто C++-ные фишки, и расширение
.hppподчёркивает это. - Хотите явно отделить C++ код от C. В смешанных проектах это спасает от путаницы.
- Следуете современным практикам. Boost, Qt (частично), многие новые библиотеки используют
.hpp.
Пример: типичный C++ заголовок с классом
// player.hpp
#ifndef PLAYER_HPP
#define PLAYER_HPP
#include <string>
#include <vector>
class Player {
public:
Player(const std::string& name, int health);
void takeDamage(int amount);
void heal(int amount);
bool isAlive() const;
const std::string& getName() const { return name_; }
private:
std::string name_;
int health_;
std::vector<std::string> inventory_;
};
#endif // PLAYER_HPP
Видите? Здесь нет extern "C", нет C-совместимых структур. Это чистый C++. Расширение .hpp сразу даёт понять: «Не пытайся подключить меня из C, я сломаюсь».
А что насчёт других расширений? .hxx, .hh, .H?
О, мир C++ многообразен. Встречаются и такие варианты:
.hxx— альтернатива.hpp, популярна в некоторых сообществах (например, в проектах, использующих CMake)..hh— редко, но метко. Иногда используется как аналог.hpp..H— на системах, где регистр важен (например, в некоторых Unix-инструментах). Лучше избегать — путаница с файлами Fortran.
На практике 99% проектов используют либо .h, либо .hpp. Остальные — экзотика для гиков.
Что говорит стандарт C++?
А ничего. Стандарт C++ не регламентирует расширения заголовочных файлов. Вообще. Ему всё равно, назовёте вы файл foo.h, foo.hpp или foo.unicorn. Директива #include работает с любым текстовым файлом.
Так что технически вы вольны выбирать любое расширение. Но сообщество выработало негласные правила, и их стоит уважать.
Практические рекомендации: как выбрать?
Вот простой чек-лист, который поможет принять решение:
| Ситуация | Рекомендуемое расширение |
|---|---|
Заголовок используется и в C,
БлогиРекомендаций по книгамЧитайте также |