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

555

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

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

Марк Инграм
источник

Ответы:

528

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

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

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

Дэвид Холм
источник
234

Я использую .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
paercebal
источник
3
Это довольно необычно во многих проектах C ++. .h файлы используются для очень неприличных вещей.
einpoklum
4
@einpoklum: Конечно. Но я стараюсь избегать поведения «Monkey See Monkey Do». В текущем случае оба расширения (и другие) доступны, поэтому я стараюсь, чтобы они действительно учитывались. Наличие этого контракта с кодом, который передается клиентам, очень полезно: все (то есть сотни разработчиков) знают, что «.H» -файлы должны использоваться клиентами, использующими компилятор C, так что нет никаких сомнений в том, что может пойти туда или не. И каждый (включая клиентов) знает, что файлы .HPP никогда не будут пытаться быть C-дружественными. Все побеждают.
paercebal
4
@paercebal, поэтому вы предлагаете .h вместо .h и .hpp над .hpp ?
Geof Sawaya
6
@GeofSawaya: нет, извините. Это привычка. При написании статей я использую расширения в верхнем регистре, чтобы различать файлы по их типу, например, «.HPP файлы». Но расширения реальных файлов, которые находятся на моем жестком диске, всегда в нижнем регистре, даже в имени нет, как «MyClass.hpp» или «module.hpp»
paercebal
4
Спасибо, @paercebal. Я становился педантичным
Geof Sawaya
48

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

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

Perculator
источник
31

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

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

Буркхард
источник
23

РЕДАКТИРОВАТЬ [Добавлено предложение от Дана Ниссенбаума]:

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

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

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

Цитата из Boost FAQ,

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

ProgramCpp
источник
Ничто из этого не является правдой, не имеет значения, является ли файл .h или .hpp, когда дело доходит до генерации кода или связывания.
Марк Ингрэм
Разве это не просто вопрос соглашения? Библиотека C ++ std предоставляет все свои заголовки без каких-либо расширений. использование ".hpp" просто указывает на то, что прототипы определены в одном и том же файле, и не будет никакого соответствующего файла .cpp.
ProgramCpp
5
Этот ответ полезен, я думаю, за исключением того, что в нем отсутствует очень простая, но важная фраза: «по соглашению, а не по правилам языка» (где-то).
Дан Ниссенбаум
13

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

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

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

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

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


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

Вводный, как и в предыдущих названных комментариях, я считаю, что 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.>include:

#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 Из того, что я знаю, по-видимому, это расширение Boost, которое придумало это .hppрасширение.

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

dhein
источник
7

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

JohnMcG
источник
6

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

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

Dynite
источник
6

Вы можете называть свои списки как угодно.

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

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

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

slashmais
источник
5

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

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

Родди
источник
5

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

CAMH
источник
5

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

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

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

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

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

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

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

ruuns
источник
4

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

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

Энцо
источник
3

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

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

Nykal
источник
2

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

Марк Рэнсом
источник
не везде, во многих примерах (например, WINDDK) они используют .hpp
marsh-wiggle
13
Я бы не назвал Microsoft «зерном», когда речь заходит о C ++.
developerbmw
@ Бретт, это когда твоя работа. И даже если это не так, это чертовски популярный компилятор.
Марк Рэнсом
@MarkRansom Я больше ссылался на историю использования C в Microsoft. IMO VC ++ - отличный компилятор.
developerbmw
1
@developerbmw Я бы сказал, что MSVC - это зерно для программ Windows, а GCC - лично для программ * nix. Насколько мне известно, именно они являются большинством других компиляторов для этих платформ.
Джастин Тайм - Восстановить Монику
1

В "Языке программирования C ++, третье издание Бьярна Страуструпа", обязательной для чтения книге C ++ № 1, он использует * .h. Поэтому я предполагаю, что лучшая практика - использовать * .h.

Тем не менее, * .hpp тоже хорошо!


источник
1
Если кто-то написал книгу о чем-то, что он узнал от других, кто узнал это из другой (может быть, по счастливой случайности) книги, написанной кем-то, у кого, возможно, был первоисточник, то это то, что они делают, но не знак для Лучшая практика.
Дхейн,
Просто упомянуть: я на самом деле dowvoted это. Но я бы проголосовал за него, если бы в нем говорилось «ISO / IEC N3690» или любой другой проект C ++ вместо «Языка программирования C ++, третье издание Бьярна Страуструпа». Хотя это было бы обоснованным аргументом, поскольку сам язык вообще не упоминает об .hppэтом.
Dhein
9
@zaibis Вы знаете, что Бьярн Страуструп изобрел C ++, верно?
тумутум
@tumtumtum: восхищен, я не знал об этом. Но в любом случае, даже в этом случае, он по-прежнему является документом комитета, поддерживающим стандарт, который стоит принять. Даже если он изобретатель языка, это уже не его решение. Таким образом, хотя это делает этот ответ более ценным, его обоснование все еще не обосновано.
Дхейн
1

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

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

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

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

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

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

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

FrankHB
источник
0

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

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

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

Майк Диммик
источник
0

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

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

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

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

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

Джастин Тайм - Восстановить Монику
источник