Для чего нужны hpp файлы

Обновлено: 04.07.2024

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

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

ОТВЕТЫ

Ответ 1

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

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

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

Ответ 2

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

Это может быть важно, когда ваш проект использует модули C и C++: как кто-то еще объяснил до меня, вы должны делать это очень осторожно, и все начинается с "контракта", который вы предлагаете через расширение

(Или.hxx, или.hh, или как там)

Этот заголовок только для C++.

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

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

Он может быть включен напрямую, будучи защищенным __cplusplus :

  • Это означает, что с точки зрения C++ C-совместимый код будет определен как extern "C" .
  • С точки зрения C весь код C будет отчетливо виден, но код C++ будет скрыт (потому что он не будет компилироваться в компиляторе C).

Или же он может быть косвенно включен в соответствующий заголовок.hpp, содержащий его с объявлением extern "C" .

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Цитата из FAQ Boost,

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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

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

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

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

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

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

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

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

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

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

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

Даже это будет соответствовать 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 Конечно, я не могу сказать, что принесут с собой некоторые будущие версии!

Ответ 12

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

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

Ответ 13

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

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

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

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

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

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

Ответ 14

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

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

Ответ 15

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

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

Ответ 16

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

Ответ 17

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

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

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

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

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

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

Ответ 18

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

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

Ответ 19

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

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

Ответ 20

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

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

В чем разница между файлами с расширениями .h и .hpp в C++? Что лучше использовать?


27.2k 10 10 золотых знаков 47 47 серебряных знаков 108 108 бронзовых знаков

Строго говоря разницы между ними нет совсем. Разница может быть лишь в том, как IDE их интерпретирует. .h , если следовать некоторой логике, это заголовок для C( .c ), тогда как .hpp это заголовок для C++( .cpp , .cxx etc.). Но всё это условности и зависят от предпочтений и используемых IDE. К примеру, в Visual Studio мы имеем .h и .cpp файлы, по умлочанию.

Единственно, на мой взгляд, где различное именование может принести пользу, это в проекте, где сочетается C и C++ код. Тогда стоит иметь .h / .c для C-кода и .hpp / .cpp для C++ когда. Других применений, кроме персональных предочтений, я не вижу.

23.4k 3 3 золотых знака 40 40 серебряных знаков 58 58 бронзовых знаков А почему тогда при попытке указать в файле .hpp , что должен делать метод класса, например так: void test::test() < . >, g++ не видел этого в упор? @egordorichev, hpp это загловок, Вы, видимо, пытаетесь использовать его как файл с кодом. но в .h , такой трюк катит, хотя это не совсем хорошо. ну вообще это не трюк, это нормальная ситуация. Просто я решил, что у вас есть .h файл с интерфейсом, который вы реализуете в .hpp файле. Мне сложно судить о gcc, т.к. я им не пользуюсь и не знаю, что ему не нравится.

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

Разные расширения для С-ных и С++-ных хедеров сделаны скорее для удобства программистов. Если видите хедер .hpp - даже не пытайтесь включать его в проект, написанный на чистом С, потому что, скорее всего, в нём будут описаны структуры, характерные только для C++ (классы, шаблоны и т. п.). Хедер .h можно (с оглядкой на то, что C не является подмножеством C++) включать в проекты, написанные на C++. Также IDE может применять различные правила форматирования и подсветки синтаксиса для хедеров .h и .hpp.

23k 3 3 золотых знака 46 46 серебряных знаков 69 69 бронзовых знаков

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

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

Ключевой момент

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

Использование заголовочных файлов стандартной библиотеки

Рассмотрим следующую программу:

Эта программа печатает « Hello, world! » в консоль с помощью std::cout . Однако эта программа никогда не предоставляла определение или объявление для std::cout , поэтому как компилятор узнает, что такое std::cout ?

Ключевой момент

Когда дело доходит до функций и переменных, стоит помнить, что заголовочные файлы обычно содержат только объявления функций и переменных, а не их определения (в противном случае может произойти нарушение правила одного определения). std::cout объявлен в заголовке iostream, но определен как часть стандартной библиотеки C++, которая автоматически подключается к вашей программе на этапе линкера.

Рисунок 1 Диаграмма процесса сборки

Рисунок 1 – Диаграмма процесса сборки

Лучшая практика

Заголовочные файлы обычно не должны содержать определений функций и переменных, чтобы не нарушать правило одного определения. Исключение сделано для символьных констант (которые мы рассмотрим в уроке «4.14 – const, constexpr и символьные константы»).

Написание собственных заголовочных файлов

А теперь вернемся к примеру, который мы обсуждали в предыдущем уроке. Когда мы закончили, у нас было два файла, add.cpp и main.cpp , которые выглядели так:

(Если вы воссоздаете этот пример с нуля, не забудьте добавить add.cpp в свой проект, чтобы он компилировался).

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

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

  1. защита заголовка, о которой мы поговорим более подробно в следующем уроке («2.11 – Защита заголовков»);
  2. фактическое содержимое файла заголовка, которое должно быть предварительными объявлениями для всех идентификаторов, которые мы хотим, чтобы другие файлы могли видеть.

Добавление заголовочного файла в проект работает аналогично добавлению исходного файла (рассматривается в уроке «2.7 – Программы с несколькими файлами исходного кода»). Если вы используете IDE, выполните такие же действия и при появлении запроса выберите Файл заголовка (или C/C++ header) вместо Файла С++ (или C/C++ source). Если вы используете командную строку, просто создайте новый файл в своем любимом редакторе.

Лучшая практика

При именовании файлов заголовков используйте расширение .h .

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

Лучшая практика

Если заголовочный файл идет в паре с файлом исходного кода (например, add.h с add.cpp ), они оба должны иметь одинаковое базовое имя ( add ).

Вот наш завершенный заголовочный файл:

Следовательно, наша программа будет правильно компилироваться и компоноваться.

Рисунок 2 Диаграмма процесса сборки

Рисунок 2 – Диаграмма процесса сборки

Включение заголовочного файла в соответствующий исходный файл

Позже вы увидите, что большинство исходных файлов включают свой соответствующий заголовочный файл, даже если он им не нужен. Зачем?

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

Когда мы углубимся в изучение стандартной библиотеки, вы будете включать множество заголовочных файлов библиотек. Если вам потребовалось включение в заголовочном файле, оно, вероятно, понадобилось вам для объявления функции. Это означает, что вам также потребуется такое же включение в исходный файл. Это приведет к тому, что в исходном файле у вас будет копия включений заголовочного файла. Включив заголовочный файл в исходный файл, исходный файл получит доступ ко всему, к чему имел доступ заголовочный файл.

При разработке библиотеки включение заголовочного файла в исходный файл может даже помочь в раннем обнаружении ошибок.

Лучшая практика

При написании исходного файла включите в него соответствующий заголовочный файл (если он существует), даже если он вам пока не нужен.

Поиск и устранение проблем

Если вы получаете ошибку компилятора, указывающую, что add.h не найден, убедитесь, что файл действительно называется add.h . В зависимости от того, как вы его создали и назвали, возможно, файл может иметь имя вроде add (без расширения), add.h.txt или add.hpp . Также убедитесь, что он находится в том же каталоге, что и остальные исходные файлы.

Угловые скобки и двойные кавычки

Вам, наверное, интересно, почему мы используем угловые скобки для iostream и двойные кавычки для add.h . Возможно, что заголовочные файлы с таким же именем могут существовать в нескольких каталогах. Использование угловых скобок и двойных кавычек помогает компилятору понять, где ему следует искать заголовочные файлы.

Когда мы используем угловые скобки, мы сообщаем препроцессору, что это заголовочный файл, который мы не писали сами. Компилятор будет искать заголовок только в каталогах, указанных в каталогах включаемых файлов (include directories). Каталоги включаемых файлов настраиваются как часть вашего проекта / настроек IDE / настроек компилятора и обычно по умолчанию используются для каталогов, содержащих заголовочные файлы, которые поставляются с вашим компилятором и/или ОС. Компилятор не будет искать заголовочный файл в каталоге исходного кода вашего проекта.

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

Правило

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

Почему у iostream нет расширения .h ?

Другой часто задаваемый вопрос: «Почему iostream (или любой другой заголовочный файл стандартной библиотеки) не имеет расширения .h ?». Ответ заключается в том, что iostream.h – это другой заголовочный файл, отличающийся от iostream ! Для объяснения требуется небольшой урок истории.

Когда C++ был только создан, все файлы в стандартной библиотеке оканчивались расширением .h . Жизнь была последовательной, и это было хорошо. Исходные версии cout и cin были объявлены в iostream.h . Когда комитет ANSI стандартизировал язык, они решили переместить все функции стандартной библиотеки в пространство имен std , чтобы избежать конфликтов имен с пользовательскими идентификаторами. Однако это представляло проблему: если бы они переместили всю функциональность в пространство имен std , ни одна из старых программ (включая iostream.h ) больше не работала бы!

Кроме того, многие библиотеки, унаследованные от C, которые всё еще используются в C++, получили префикс c (например, stdlib.h стал cstdlib ). Функциональные возможности этих библиотек также были перенесены в пространство имен std , чтобы избежать конфликтов имен.

Лучшая практика

При включении заголовочного файла из стандартной библиотеки используйте версию без расширения (без .h ), если она существует. Пользовательские заголовочные файлы по-прежнему должны использовать расширение .h .

Включение заголовочных файлов из других каталогов

Другой распространенный вопрос связан с тем, как включать заголовочные файлы из других каталогов.

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

Лучший способ – сообщить вашему компилятору или IDE, что у вас есть куча заголовочных файлов в каком-то другом месте, чтобы он смотрел туда, когда не может найти их в текущем каталоге. Обычно это можно сделать, установив путь включения (include path) или каталог поиска (search directory) в настройках проекта в IDE.

Для пользователей Visual Studio

Кликните правой кнопкой мыши на своем проекте в обозревателе решений и выберите Свойства (Properties), затем вкладку Каталоги VC++.(VC++ Directories). Здесь вы увидите строку с названием «Включаемые каталоги» (Include Directories). Добавьте каталоги, в которых компилятор должен искать дополнительные заголовочные файлы.

Для пользователей Code::Blocks

В Code:: Blocks перейдите в меню Project (Проект) и выберите Build Options (Параметры сборки), затем вкладку Search directories (Каталоги поиска). Добавьте каталоги, в которых компилятор должен искать дополнительные заголовочные файлы.

Для пользователей GCC/G++

Используя g++, вы можете использовать параметр -I , чтобы указать альтернативный каталог для включения.

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

Заголовочные файлы могут включать другие заголовочные файлы

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

Лучшая практика

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

Вопрос: Я не включил <someheader.h> , и моя программа всё равно работала! Почему?

Это один из наиболее часто задаваемых вопросов. Ответ: скорее всего, он работает, потому что вы включили какой-то другой заголовок (например, <iostream> ), который сам включает <someheader.h> . Несмотря на то, что ваша программа будет компилироваться, в соответствии с приведенными выше рекомендациями вам не следует полагаться на это. То, что компилируется у вас, может не компилироваться на машине друга.

Лучшая практика

Рекомендации по использованию заголовочных файлов

Вот еще несколько рекомендаций по созданию и использованию заголовочных файлов.

А вы какое расширение используете для заголовочных файлов C++?

По идее, .hpp правильнее, так как .h это всё-таки сишный заголовок и, соответственно, у них могут быть различия.




Пускай, это и сишный заголовок, но он используется в с++-проекте, и принимают его .cpp-файлы, а не .с. так что путаницы не возникает. Если возникает, то можно вместо .h использовать .H, но тогда во имя Луны следует использовать .C вместо .cpp. Хотя, вообще-то и .hpp никто использовать не запрещает, просто он не очень-то и распространён



hpp для меньшей неоднозначности. Так и ассоциировать языки с типами файлов проще.



*.h везде на работе и сам для себя.


hpp, хотя кое-где и .h, зависит от проекта, IDE и т.д..



hpp - борланданутый даунизм. Ну как ты это расшифровывать собираешься? Header Plus Plus? Мерзость же.

Да, сразу вспомнился 2004 год, шиндовс и пятый дебилдер.

hxx и cxx уже был вариант?

h где описание класса, hpp где еще и реализация.

еще, кстати h++ есть. Пару раз видел.

У нас в проекте есть и те и другие. Расширение выбираю исходя из уже существующих файлов в той же папке (кого больше - такое и выбираю)

По мере увеличения размера программ весь код уже не помещается в нескольких файлах, записывать каждый раз предварительные объявления для функций, которые мы хотим использовать, но которые находятся в других файлах, становится всё утомительнее и утомительнее. Хорошо было бы, если бы все предварительные объявления находились в одном месте, не так ли?

Заголовочные файлы из Стандартной библиотеки C++

Рассмотрим следующую программу:

Результат выполнения программы:

Как правило, в заголовочных файлах записываются только объявления, без определений. Следовательно, если cout только объявлен в заголовочном файле iostream, то где же он определяется? Ответ: в Стандартной библиотеке С++, которая автоматически подключается к вашему проекту на этапе линкинга.


Пишем свои собственные заголовочные файлы

Теперь давайте вернемся к примеру, который мы обсуждали на предыдущем уроке. У нас было два файла: add.cpp и main.cpp.

int add ( int x , int y ) ; // предварительное объявление с использованием прототипа функции std :: cout << "The sum of 3 and 4 is " << add ( 3 , 4 ) << std :: endl ;

Примечание: Если вы создаете все файлы заново, то не забудьте добавить add.cpp в свой проект, чтобы он был подключен к компиляции.

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

Написать свой собственный заголовочный файл не так уж и сложно. Заголовочные файлы состоят из двух частей:

Директивы препроцессора — в частности, header guards, которые предотвращают вызов заголовочного файла больше одного раза из одного и того же файла (об этом детально на следующем уроке).

Содержимое заголовочного файла — набор объявлений.

Все ваши заголовочные файлы (которые вы написали самостоятельно) должны иметь расширение .h .

// Начнем с директив препроцессора. ADD_H – это произвольное уникальное имя (обычно используется имя заголовочного файла) int add ( int x , int y ) ; // прототип функции add() (не забывайте точку с запятой в конце!)

Чтобы использовать этот файл в main.cpp, вам сначала нужно будет подключить его к проекту.

main.cpp, в котором мы подключаем add.h:

std :: cout << "The sum of 3 and 4 is " << add ( 3 , 4 ) << std :: endl ;

add.cpp остается без изменений:

Если вы получили ошибку от линкера, что функция аdd() не определена, то убедитесь, что вы корректно подключили add.cpp к вашему проекту (и к компиляции тоже)!

Стоит отметить, что одни заголовочные файлы могут подключать другие заголовочные файлы. Тем не менее, так делать не рекомендуется.

Почему iostream пишется без окончания .h?

Когда C++ только создавался, все файлы библиотеки Runtime имели окончание .h. Оригинальные версии cout и cin объявлены в iostream.h. При стандартизации языка С++ комитетом ANSI, решили перенести все функции из библиотеки Runtime в пространствo имен std, чтобы предотвратить возможность возникновения конфликтов имен с пользовательскими идентификаторами (что, между прочим, является хорошей идеей). Тем не менее, возникла проблема: если все функции переместить в пространство имен std, то старые программы переставали работать!

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

Кроме того, многие библиотеки, унаследованные от языка Cи, которые до сих пор используются в C++, также были продублированы с добавлением префикса c (например, stdlib.h стал cstdlib). Функционал этих библиотек также перенесли в пространство имен std, чтобы избежать возможность возникновения конфликтов имен с пользовательскими идентификаторами.

Можно ли записывать определения в заголовочных файлах?

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

Иногда делаются исключения для простых функций, которые вряд ли изменятся (например, где определение состоит всего лишь из одной строки).

Советы

Вот несколько советов по написанию собственных заголовочных файлов:

Всегда используйте директивы препроцессора.

Не определяйте переменные в заголовочных файлах, если это не константы. Заголовочные файлы следует использовать только для объявлений.

Читайте также: