* .h или * .hpp для ваших определений классов

440

Я всегда использовал файл *.h для определения моего класса, но, прочитав некоторый код библиотеки boost, я понял, что они все используют *.hpp. У меня всегда было отвращение к расширению этого файла, я думаю, в основном потому, что я не привык к нему.

В чем преимущества и недостатки использования *.hpp над *.h?

Теги:
header

20 ответов

457
Лучший ответ

Вот несколько причин для различного наименования заголовков C vs С++:

  • Автоматическое форматирование кода, у вас могут быть разные рекомендации по форматированию кода на C и С++. Если заголовки разделены расширением, вы можете настроить ваш редактор на автоматическое применение соответствующего форматирования.
  • Именование, я был в проектах, где были библиотеки, написанные на C, а затем оболочки были реализованы на С++. Поскольку заголовки обычно имели похожие имена, то есть Feature.h vs Feature.hpp, их было легко отличить друг от друга.
  • Включение, возможно, ваш проект имеет более подходящие версии, доступные на С++, но вы используете версию C (см. выше). Если заголовки названы после языка, в котором они реализованы, вы можете легко определить все C-заголовки и проверить версии С++.

Помните, что C - это не С++, и может быть очень опасно смешивать и сопоставлять, если вы не знаете, что делаете. Именование ваших источников соответствующим образом помогает вам отличать языки.

198

Я использую.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
  • 1
    Это довольно необычно во многих проектах C ++. .h файлы используются для очень неприличных вещей.
  • 3
    @einpoklum: Конечно. Но я стараюсь избегать поведения «Monkey See Monkey Do». В текущем случае оба расширения (и другие) доступны, поэтому я стараюсь, чтобы они действительно учитывались. Наличие этого контракта с кодом, который передается клиентам, очень полезно: все (то есть сотни разработчиков) знают, что «.H» -файлы должны использоваться клиентами, использующими компилятор C, поэтому нет никаких сомнений в том, что можно туда сделать или не. И каждый (включая клиентов) знает, что файлы «.HPP» никогда не будут пытаться быть C-дружественными. Все побеждают.
Показать ещё 3 комментария
42

Я всегда рассматривал заголовок .hpp как своего рода portmanteau файлов .h и .cpp... заголовок, который также содержит сведения о реализации.

Обычно, когда я видел (и использовал) .hpp в качестве расширения, нет соответствующего файла .cpp. Как говорили другие, это не сложное и быстрое правило, просто как я обычно использую файлы .hpp.

23

Не важно, какое расширение вы используете. Любой из них в порядке.

Я использую *.h для C и *.hpp для С++.

20

EDIT [Добавлено предложение от Дэна Ниссенбаума]:

По одному соглашению файлы .hpp используются, когда прототипы определены в самом заголовке. Такие определения в заголовках полезны в случае шаблонов, поскольку компилятор генерирует код для каждого типа только при создании экземпляра. Следовательно, если они не определены в заголовочных файлах, их определения не будут разрешены во время соединения с другими единицами компиляции. Если ваш проект - это только проект на C++, который сильно использует шаблоны, это соглашение может быть полезно.

Некоторые библиотеки шаблонов, которые придерживаются этого соглашения, предоставляют заголовки с расширением .hpp, чтобы указать, что у них нет соответствующих файлов .cpp.

В некоторых других библиотеках шаблонов используется другое соглашение, например, использование .h для заголовков C и .hpp для С++; хорошим примером может служить библиотека ускорения.

Цитата из FAQ Boost,

Расширения файлов сообщают "тип" файла, как для людей и к компьютерным программам. Расширение '.h' используется для заголовка C файлы и, следовательно, сообщает о неправильном заголовке С++ файлы. Использование без расширения ничего не сообщает и проводит проверку содержимого файла для определения типа. Использование ".hpp" недвусмысленно идентифицирует его как заголовочный файл С++ и хорошо работает на практике. (Райнер Дейк)

  • 0
    Ничего из этого не является правдой, не имеет значения, является ли файл .h или .hpp, когда дело доходит до генерации кода или связывания.
  • 0
    Разве это не просто вопрос соглашения? Библиотека C ++ std предоставляет все свои заголовки без каких-либо расширений. Использование «.hpp» просто указывает, что прототипы определены в одном и том же файле, и не будет никакого соответствующего файла .cpp.
Показать ещё 1 комментарий
10

Недавно я начал использовать *.hpp для заголовков С++.

Причина в том, что я использую emacs в качестве основного редактора и автоматически переходит в c-режим при загрузке файла *.h и в режиме С++ при загрузке файла *.hpp.

Помимо этого факта я не вижу веских оснований для выбора *.h над *.hpp или наоборот.

  • 6
    Лично я думаю, что выделение C ++ является хорошей идеей даже в заголовках C. Я был на обоих концах ситуации, когда кто-то хочет включить ваш заголовок C из C ++, но он использует ключевое слово C ++ в качестве имени параметра ...
6

Я предпочитаю .hpp для С++, чтобы дать понять как редакторам, так и другим программистам, что это заголовок С++, а не заголовочный файл C.

6

Вы можете позвонить, что включает в себя все, что вам нравится.

Просто нужно указать это полное имя в #include.

Я предлагаю, если вы работаете с C, чтобы использовать .h, а когда с С++ использовать .hpp.

Это, в конце концов, просто соглашение.

5

Я отвечаю на это как напоминание, чтобы указать на мой комментарий (я) к "user1949346" ответ на этот же ОП.


Так что многие уже ответили: в любом случае это хорошо. Далее следует акцент на собственных впечатлениях.

Вводный, как и в предыдущих названных комментариях, мое мнение C++ расширения заголовка C++ предлагаются как .h если на самом деле нет причин против этого.

Поскольку документы ИСО/МЭК использовать эти обозначения файлов заголовков и не совпадающей строки в .hpp происходит даже на их языке документаций о C++.

Но теперь я стремлюсь по приемлемой причине, ПОЧЕМУ любой путь в порядке, и особенно почему это не предмет языка, который он сам.

Итак, поехали.

Документация C++ (на самом деле я ссылаюсь на версию N3690) определяет, что заголовок должен соответствовать следующему синтаксису:

2.9 Имена заголовков

header-name:
    < h-char-sequence >
    " q-char-sequence "
h-char-sequence:
    h-char
    h-char-sequence h-char
h-char:
    any member of the source character set except new-line and >
q-char-sequence:
    q-char
    q-char-sequence q-char
q-char:
    any member of the source character set except new-line and "

Таким образом, как мы можем извлечь из этой части, имя файла заголовка также может быть любым, допустимым в исходном коде. За исключением того, что содержит символы '\n' и в зависимости от того, должен ли он быть включен в <> он не может содержать >. Или другой способ, если он включен "" -include, ему не разрешено содержать ".

Другими словами: если у вас была среда, поддерживающая имена файлов, такие как prettyStupidIdea.>, prettyStupidIdea.> вроде:

#include "prettyStupidIdea.>"

будет действительным, но:

#include <prettyStupidIdea.>>

будет недействительным. И наоборот.

И даже

#include <<.<>

будет допустимым включаемым именем файла заголовка.

Даже это будет соответствовать C++, это была бы довольно глупая идея, правда.

И вот почему .hpp подходит.

Но это не результат комитетов, разрабатывающих решения для языка!

Поэтому обсуждение использования .hpp аналогично обсуждению .cc, .mm или всего, что я читал в других постах на эту тему.

Я должен признать, что я понятия не имею, где .hpp пришел от 1, но я бы поставил изобретатель некоторого синтаксического анализа инструмента, IDE или что - то другое, связанный с C++ пришел к этой идее, чтобы оптимизировать некоторые внутренние процессы или просто придумать какую - то ( наверное даже для них обязательно) новые соглашения об именах.

Но это не часть языка.

И всякий раз, когда кто-то решает использовать это таким образом. Может быть потому, что ему нравится не больше всего или потому, что некоторые приложения процесса требуют, он никогда 2 является требованием языка. Поэтому тот, кто говорит "pp - это потому, что он используется с C++", просто ошибается в отношении определения языков.

C++ позволяет все, что касается предыдущего абзаца. И если есть что-то, что комитет предложил использовать, то он использует .h поскольку это расширение используется во всех примерах документа ISO.

Заключение:

Пока вы не видите/не чувствуете необходимости использовать .h .hpp или наоборот, вам не стоит беспокоиться. Потому что оба будут формировать правильное имя заголовка одинакового качества по отношению к стандарту. И поэтому все, что ТРЕБУЕТ вам использовать .h или .hpp является дополнительным ограничением стандарта, которое может даже противоречить другим дополнительным ограничениям, не совместимым друг с другом. Но поскольку OP не упоминает никаких дополнительных языковых ограничений, это единственный правильный и приемлемый ответ на вопрос

"*.h или *.hpp для ваших определений классов":

Оба являются одинаково правильными и применимыми до тех пор, пока нет внешних ограничений.


1Из того, что я знаю, по-видимому, это фреймворк .hpp который .hpp расширение .hpp.

2Конечно, я не могу сказать, что принесут с собой некоторые будущие версии!

5

С++ ( "C Plus Plus" ) имеет смысл как .cpp

Наличие файлов заголовков с расширением .hpp не имеет одинакового логического потока.

  • 5
    Согласен; «заголовок плюс плюс» не совсем подходит.
5

В одном из моих заданий в начале 90-х мы использовали .cc и .hh для исходных и заголовочных файлов соответственно. Я по-прежнему предпочитаю его по всем альтернативам, возможно, потому что это проще всего напечатать.

4

К счастью, это просто.

Вы должны использовать расширение .hpp, если вы работаете с С++, и вы должны использовать .h для C или для смешивания C и С++.

4

Как уже упоминалось выше, я также предпочитаю использовать .hpp для библиотек только для заголовков, которые используют шаблонные классы/функции. Я предпочитаю использовать .h для файлов заголовков, сопровождаемых исходными файлами .cpp или общими или статическими библиотеками.

Большинство разрабатываемых библиотек основаны на шаблонах и поэтому должны быть только заголовками, но при написании приложений я склонен отделять декларацию от реализации и в конечном итоге с файлами .h и .cpp

4

Bjarne Stroustrup и Herb Sutter имеют отношение к этому вопросу в своих основных принципах С++, описанных в: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-source, который также ссылается на последние изменения в стандартном расширении (С++ 11, С++ 14 и т.д.)

SF.1: используйте суффикс .cpp для файлов кода и .h для файлов интерфейса, если ваш Проект Y еще не соответствует другому соглашению Причина

Это давняя конвенция. Но последовательность важнее, поэтому, если ваш проект использует что-то еще, следуйте этому. Примечание

Это соглашение отражает общую схему использования: заголовки чаще всего разделяются с C для компиляции как С++ и C, который обычно использует .h, и он проще назвать все заголовки .h вместо разных расширений для только те заголовки, которые предназначены для совместного использования с C. С другой стороны, файлы реализации редко используются совместно с C, и поэтому обычно должны быть отличается от .c файлов, поэтому обычно лучше всего назвать все С++ реализация файлов что-то еще (например,.cpp).

Конкретные имена .h и .cpp не требуются (рекомендуется только в качестве по умолчанию), а другие имена широко используются. Примерами являются .hh,.C и .cxx. Используйте такие имена эквивалентно. В этом документе мы ссылаемся на .h и .cpp > как стенографию для файлов заголовков и реализации, хотя фактическое расширение может быть другим.

Ваша IDE (если вы ее используете) может иметь сильные мнения о достаточности.

Я не большой поклонник этого соглашения, потому что, если вы используете популярную библиотеку, например boost, ваша последовательность уже нарушена, и вам лучше использовать .hpp.

4

Codegear С++ Builder использует .hpp для файлов заголовков, автоматически генерируемых из исходных файлов Delphi, и .h файлов для ваших собственных файлов заголовков.

Итак, когда я пишу заголовочный файл С++, я всегда использую .h.

2

Я использую .h, потому что это то, что использует Microsoft, и то, что создает генератор кода. Не нужно идти против зерна.

  • 0
    не везде, во многих примерах (например, WINDDK) они используют .hpp
  • 12
    Я бы не назвал Microsoft «зерном», когда речь заходит о C ++.
Показать ещё 3 комментария
1

Инструментам и людям легко отличить что-то. Что это.

В обычном использовании (с помощью boost и т.д.) .hpp - это, в частности, заголовки С++. С другой стороны, .h для не-С++ - только заголовки (в основном C). Точно определить язык содержимого, как правило, сложно, так как существует много нетривиальных случаев, поэтому это различие часто делает готовый к использованию инструмент легким для записи. Для людей, после получения конвенции, он также легко запоминается и прост в использовании.

Однако я бы отметил, что сама конвенция не всегда работает, как и ожидалось.

  • Он не принуждается спецификацией языков, ни C, ни С++. Существует много проектов, которые не соответствуют конвенции. Как только вам нужно объединить (смешать) их, это может быть неприятно.
  • .hpp сам по себе не единственный выбор. Почему бы не .hh или .hxx? (Хотя в любом случае вам обычно требуется хотя бы одно обычное правило о именах файлов и путях.)

Я лично использую как .h, так и .hpp в моих проектах на С++. Я не следую вышеприведенному соглашению, потому что:

  • Языки, используемые каждой частью проектов, явно документированы. Нет возможности смешать C и С++ в том же модуле (каталог). Каждая библиотека 3rdparty должна соответствовать этому правилу.
  • Также документируются соответствующие спецификации языка и разрешенные языковые диалекты, используемые проектами. (Фактически, я даже документирую источник стандартных функций и исправления ошибок (по стандартному языку)). Это несколько более важно чем различать используемые языки, поскольку он слишком подвержен ошибкам, а стоимость теста (например, совместимость с компиляторами) может быть значительным (сложным и трудоемким), особенно в проекте, который уже находится в почти чистом С++. Имена файлов слишком слабы, чтобы справиться с этим.
  • Даже для одного и того же диалекта С++ могут быть более важные свойства, подходящие для разницы. Например, см. Соглашение ниже.
  • Имена файлов - это, по сути, фрагменты хрупких метаданных. Нарушение конвенции не так легко обнаружить. Чтобы быть стабильным в отношении контента, инструмент должен в конечном итоге не только зависеть от имен. Разница между расширениями - это всего лишь намек. Не следует ожидать, что инструменты, использующие его, будут вести себя одинаково все время, например. обнаружение языка .h файлов на github.com. (Возможно, что-то в комментариях, таких как shebang, чтобы эти исходные файлы были лучшими метаданными, но он даже не является обычным, как имена файлов, поэтому также не надежны в целом.)

Обычно я использую .hpp в заголовках С++, и заголовки должны использоваться (поддерживаться) только в виде заголовка, например. как библиотеки шаблонов. Для других заголовков в .h либо имеется соответствующий файл .cpp как реализация, либо это не-С++-заголовок. Последнее тривиально дифференцировать через содержимое заголовка людьми (или инструментами с явными встроенными метаданными, если это необходимо).

0

Нет никакого преимущества для какого-либо конкретного расширения, кроме того, что у вас может быть другое значение для вас, компилятора и/или ваших инструментов. header.h - допустимый заголовок. header.hpp является допустимым заголовком. header.hh является допустимым заголовком. header.hx является допустимым заголовком. h.header является допустимым заголовком. this.is.not.a.valid.header является допустимым заголовком в отрицании. ihjkflajfajfklaf является допустимым заголовком. Пока имя может быть правильно проанализировано компилятором, а файловая система поддерживает его, он является допустимым заголовком, и единственным преимуществом его расширения является то, что он читает в нем.

Если говорить, что возможность точно делать предположения на основе расширения очень полезна, поэтому было бы разумно использовать легко понятный набор правил для ваших файлов заголовков. Лично я предпочитаю делать что-то вроде этого:

  • Если есть уже установленные правила, следуйте им, чтобы предотвратить путаницу.
  • Если все исходные файлы в проекте предназначены для одного языка, используйте .h. Там нет двусмысленности.
  • Если некоторые заголовки совместимы с несколькими языками, а другие совместимы только с одним языком, расширения основаны на самом ограничительном языке, совместимом с заголовком. Заголовок, совместимый с C или с C и С++, получает .h, а заголовок, совместимый с С++, но не C, получает .hpp или .hh или что-то вроде этого.

Это, конечно, является одним из многих способов обработки расширений, и вы не можете доверять своему первому впечатлению, даже если все кажется простым. Например, я видел упоминание использования .h для обычных заголовков и .tpp для заголовков, содержащих только определения для шаблонных функций-членов класса, с .h файлами, которые определяют шаблонные классы, включая файлы .tpp, которые определяют их функции-члены (вместо заголовка .h, содержащего как объявление функции, так и определение). В другом примере многие люди всегда отражают язык заголовка в своем расширении, даже если нет возможности двусмысленности; для них .h всегда является заголовком C, а .hpp (или .hh, или .hxx и т.д.) всегда является заголовком С++. И все же, некоторые люди используют .h для "заголовка, связанного с исходным файлом" и .hpp для "заголовка со всеми функциями, определенными в строке".

Учитывая это, основное преимущество будет заключаться в том, чтобы последовательно называть ваши заголовки в одном стиле и сделать этот стиль понятным для всех, кто изучает ваш код. Таким образом, любой, кто знаком с вашим обычным стилем кодирования, сможет определить, что вы имеете в виду с любым заданным расширением, просто беглым взглядом.

0

В "языке программирования С++, третьем выпуске Bjarne Stroustrup", читаемой С++ книге nº1, он использует *.h. Поэтому я предполагаю, что наилучшей практикой является использование *.h.

Однако, *.hpp тоже отлично!

  • 1
    Если кто-то написал книгу о чем-то, что он узнал от других, кто узнал это из другой (может быть, по счастливой случайности) книги, написанной кем-то, у кого, возможно, был первоисточник, то это то, что они делают, но не знак для Лучшая практика.
  • 0
    Просто упомянуть: я на самом деле dowvoted это. Но я бы проголосовал за него, если бы в нем говорилось «ISO / IEC N3690» или любой другой проект C ++ вместо «Язык программирования C ++, третье издание Бьярна Страуструпа». Хотя это было бы верным .hpp сам язык не упоминает .hpp вообще.
Показать ещё 2 комментария
0

Расширение исходного файла может иметь смысл для вашей системы сборки, например, у вас может быть правило в файле makefile для файлов .cpp или .c, или ваш компилятор (например, Microsoft cl.exe) может скомпилировать файл как C или С++ в зависимости от расширения.

Поскольку вы должны предоставить полное имя файла директиве #include, расширение файла заголовка не имеет значения. Вы можете включить файл .c в другой исходный файл, если хотите, потому что он включает только текстовый текст. У вашего компилятора может быть возможность сбрасывать предварительно обработанный вывод, который сделает это ясно (Microsoft: /P для предварительной обработки файла, /E для предварительной обработки stdout, /EP, чтобы опустить директивы #line, /C сохранить комментарии)

Вы можете использовать .hpp для файлов, которые имеют отношение только к среде С++, то есть они используют функции, которые не будут компилироваться в C.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню