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

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

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


person Mark Ingram    schedule 30.09.2008    source источник


Ответы (20)


Вот несколько причин, по которым заголовки C и C ++ называются по-разному:

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

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

person David Holm    schedule 30.09.2008
comment
Проголосовали за последний абзац! - person Richard McFriend Oluwamuyiwa; 08.04.2021

Я использую .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
person paercebal    schedule 30.09.2008
comment
Это довольно необычно для многих проектов на C ++. Файлы .h используются для очень не-C'ish вещей. - person einpoklum; 12.03.2016
comment
@einpoklum: Конечно. Но я стараюсь избегать поведения обезьяны, видящей, как обезьяна делает. В текущем случае доступны оба расширения (и другие), поэтому я стараюсь, чтобы они действительно учитывались. Наличие этого контракта с кодом, который используется совместно с клиентами, очень полезно: каждый (то есть сотни разработчиков) знает, что файлы .H должны использоваться клиентами, использующими компилятор C, поэтому нет никаких сомнений в том, что может быть там или нет. И все (включая клиентов) знают, что файлы .HPP никогда не будут пытаться быть дружественными к C. Все выигрывают. - person paercebal; 13.03.2016
comment
@paercebal, значит, вы предлагаете .H вместо .h и .HPP вместо .hpp? - person Geof Sawaya; 19.08.2016
comment
@GeofSawaya: Нет, извините. Это привычка. При написании статей я использую расширения в верхнем регистре, чтобы различать файлы по типу, например файлы .HPP. Но расширения фактических файлов, которые есть на моем жестком диске, всегда в нижнем регистре, даже в имени нет, например MyClass.hpp или module.hpp - person paercebal; 20.08.2016
comment
Спасибо, @paercebal. Я становился педантичным - person Geof Sawaya; 26.08.2016

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

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

person Perculator    schedule 30.09.2008

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

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

person Burkhard    schedule 30.09.2008

ИЗМЕНИТЬ [добавлено предложение Дэна Ниссенбаума]:

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

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

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

Цитата из FAQ по Boost,

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

person ProgramCpp    schedule 03.12.2013
comment
Ничего из этого неверно, когда дело доходит до генерации кода или связывания, не имеет значения, является ли файл .h или .hpp. - person Mark Ingram; 03.12.2013
comment
разве это не вопрос условности? Библиотека std C ++ предоставляет все свои заголовки без какого-либо расширения. использование .hpp просто указывает на то, что прототипы определены в одном файле и не будет соответствующего файла .cpp. - person ProgramCpp; 04.12.2013
comment
Я думаю, что этот ответ полезен, за исключением того, что в нем отсутствует очень простая, но важная фраза: по соглашению, а не по правилам языка (где-то). - person Dan Nissenbaum; 15.12.2014

Я отвечаю на это как напоминание, чтобы указать на мои комментарии к ответу "user1949346" на этот же OP.


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

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

Поскольку в документах ISO / IEC используется эта нотация файлов заголовков, и в документации на их языке о C++ даже не встречается строка, соответствующая .hpp.

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

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

Документация 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 "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 расширение придумал именно фреймворк boost.

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

person dhein    schedule 08.03.2016

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

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

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

person Serge    schedule 30.09.2008
comment
Лично я считаю, что подсветка C ++ - хорошая идея даже в заголовках C. Я был на обоих концах ситуации, когда кто-то хотел включить ваш заголовок C из C ++, но он использует ключевое слово C ++ в качестве имени параметра ... - person Steve Jessop; 30.09.2008

Вы можете называть свои включения как угодно.

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

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

В конце концов, это просто условность.

person slashmais    schedule 30.09.2008

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

person JohnMcG    schedule 30.09.2008

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

Заголовочные файлы с расширением .hpp не имеют такой логической последовательности.

person Dynite    schedule 30.09.2008

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

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

person Roddy    schedule 30.09.2008

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

person camh    schedule 30.09.2008

Бьярн Страуструп и Херб Саттер сформулировали этот вопрос в своих рекомендациях по ядру 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.

person ruuns    schedule 13.08.2017

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

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

person Enzo    schedule 18.08.2017

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

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

person Nykal    schedule 05.09.2017

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

person Mark Ransom    schedule 30.09.2008
comment
не везде, во многих примерах (например, WINDDK) используется .hpp - person marsh-wiggle; 21.07.2014
comment
Когда речь заходит о C ++, я бы не назвал Microsoft «зерном». - person developerbmw; 17.08.2014
comment
@ Бретт, это твоя работа. И даже если это не так, это чертовски популярный компилятор. - person Mark Ransom; 19.08.2014
comment
@MarkRansom Я больше имел в виду историю использования Microsoft C. IMO VC ++ - отличный компилятор. - person developerbmw; 20.08.2014
comment
@developerbmw Я бы сказал, что MSVC - это зерно для программ Windows, а GCC - это зерно для программ * nix, лично. Насколько мне известно, это те самые компиляторы для этих платформ, с которыми стараются оставаться совместимыми. - person Justin Time - Reinstate Monica; 15.06.2016

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

При обычном использовании (ускорением и т. Д.) .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 ++. Последнее легко различить по содержимому заголовка людьми (или инструментами с явными встроенными метаданными, если необходимо).

person FrankHB    schedule 30.01.2016

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

Однако и * .hpp тоже подойдет!

person Community    schedule 29.05.2013
comment
Если кто-то написал книгу о чем-то, чему он научился у других, которые узнали это из другой (возможно, той же самой) книги, написанной кем-то, у кого, возможно, был доступ к первоисточнику, то это то, что они делают, что угодно, но не цель быть передовой практикой. - person dhein; 08.03.2016
comment
Просто упомяну: я на самом деле дауотировал это. Но я бы поддержал его, если бы там говорилось, что ISO / IEC N3690 или любой другой проект C ++ заменяет «Язык программирования C ++, третье издание» Бьярна Страуструпа. Хотя это было бы правильным аргументом, поскольку в самом языке вообще нет упоминания .hpp. - person dhein; 08.03.2016
comment
@zaibis, вы ведь знаете, что Бьярн Страуструп изобрел C ++? - person tumtumtum; 13.06.2016
comment
@tumtumtum: я не знал об этом. Но в любом случае, даже в этом случае, это все еще документ комитета, поддерживающий стандарт, который и является справочной информацией. Даже если он изобретатель языка, это уже не его решение. Таким образом, хотя это и делает этот ответ более ценным, его аргументация все еще не обоснована. - person dhein; 13.06.2016

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

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

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

person Mike Dimmick    schedule 30.09.2008

У какого-либо конкретного расширения нет никаких преимуществ, кроме того, что одно может иметь другое значение для вас, компилятора и / или ваших инструментов. 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 для «заголовка со всеми встроенными функциями».

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

person Justin Time - Reinstate Monica    schedule 15.06.2016