*.h или *.hpp для определения ваших классов?
У меня всегда были файлы с расширением .h
для определения классов, но после изучения кода библиотеки Boost я заметил, что они используют .hpp
. У меня всегда была предвзятость к этому расширению, вероятно, потому что я к нему не привык.
Какие преимущества и недостатки использования .hpp
по сравнению с .h
?
5 ответ(ов)
Вот несколько причин, по которым заголовки для C и C++ могут иметь разные имена:
Автоматическое форматирование кода: У вас могут быть разные руководства по форматированию для C и C++ кода. Если заголовки разделены по расширению, вы можете настроить свой редактор так, чтобы он автоматически применял соответствующее форматирование.
Именование: Я участвовал в проектах, где использовались библиотеки, написанные на C, а затем были реализованы обертки на C++. Поскольку заголовки обычно имели схожие названия, например, Feature.h и Feature.hpp, их легко было различить.
Включение заголовков: Возможно, что в вашем проекте доступны более подходящие версии заголовков, написанные на C++, но вы используете версию на C (см. предыдущий пункт). Если заголовки названы в соответствии с языком, на котором они написаны, вы можете легко выделить все заголовки на C и проверить наличие их C++ версий.
Помните, что C это не C++ и смешивание этих языков может быть очень опасным, если вы не знаете, что делаете. Подходящее именование ваших исходников помогает различать языки.
Я использую расширение .hpp, потому что хочу, чтобы пользователь мог различать, какие заголовки являются заголовками C++, а какие — заголовками C.
Это может быть важно, когда ваш проект использует как модули C, так и C++: как кто-то уже объяснял ранее, подходить к этому нужно очень осторожно, и всё начинается с "контракта", который вы предлагаете через расширение.
.hpp : Заголовки C++
(Или .hxx, или .hh, или любое другое)
Этот заголовок предназначен только для C++.
Если вы находитесь в C-модуле, даже не пытайтесь его включить. Вам это не понравится, потому что не было никаких усилий, чтобы сделать его совместимым с C (потеряется слишком много, например, перегрузка функций, пространства имен и так далее).
.h : Совместимые заголовки C/C++ или чисто C-заголовки
Этот заголовок может быть включён как из исходного файла на C, так и из исходного файла на C++, прямо или косвенно.
Он может быть включён напрямую, защищённый макросом __cplusplus
:
- Это значит, что с точки зрения C++ код, совместимый с C, будет определён как
extern "C"
. - С точки зрения C весь C-код будет очевиден, но C++ код будет скрыт (поскольку он не скомпилируется в компиляторе C).
Например:
#ifndef MY_HEADER_H
#define MY_HEADER_H
#ifdef __cplusplus
extern "C"
{
#endif
void myCFunction();
#ifdef __cplusplus
} // extern "C"
#endif
#endif // MY_HEADER_H
Или его можно включить косвенно через соответствующий заголовок .hpp, который обернёт его в объявление extern "C"
.
Например:
#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
extern "C"
{
#include "my_header.h"
}
#endif // MY_HEADER_HPP
А также:
#ifndef MY_HEADER_H
#define MY_HEADER_H
void myCFunction();
#endif // MY_HEADER_H
Я всегда рассматривал расширение .hpp
как некий «смешанный» вариант для файлов .h
и .cpp
... это заголовочный файл, который содержит также детали реализации.
Обычно, когда я вижу (и использую) расширение .hpp
, соответствующего файла .cpp
нет. Как и другие отмечали, это не строгое правило, а скорее то, как я обычно использую файлы .hpp
.
Не имеет значения, какое расширение использовать. Оба варианта подходят.
Я использую *.h
для C и *.hpp
для C++.
EDIT [Добавлено предложение от Дэна Ниссенбаума]:
Согласно одной из конвенций, файлы с расширением .hpp используются, когда прототипы определяются в самом заголовочном файле. Такие определения в заголовках полезны в случае с шаблонами, поскольку компилятор генерирует код для каждого типа только при инстанцировании шаблона. Следовательно, если они не определены в заголовочных файлах, их определения не будут разрешены во время линковки из других единиц компиляции. Если ваш проект является исключительно C++ проектом и активно использует шаблоны, эта конвенция окажется полезной.
Некоторые библиотеки шаблонов, которые придерживаются этой конвенции, предоставляют заголовки с расширением .hpp, чтобы указать, что у них нет соответствующих файлов .cpp.
Другая конвенция предполагает использование .h для C-заголовков и .hpp для C++; хорошим примером является библиотека Boost.
Цитата из FAQ Boost:
Расширения файлов сообщают о "типе" файла как для людей, так и для компьютерных программ. Расширение '.h' используется для заголовочных файлов C, и, следовательно, передает неправильную информацию о заголовочных файлах C++. Использование без расширения ничего не сообщает и заставляет проверять содержимое файла для определения типа. Использование '.hpp' однозначно идентифицирует его как заголовочный файл C++, и это хорошо работает на практике. (Рейнер Дейк)
Что такое Правило трёх?
Разница между const int*, const int * const и int * const?
Имеют ли круглые скобки после имени типа значение при использовании new?
Как удалить элемент из std::vector<> по индексу?
Чтение файла построчно с использованием ifstream в C++