* .h або * .hpp для визначень вашого класу


554

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

Які переваги та недоліки використання *.hppпонад *.h?

Відповіді:


528

Ось декілька причин того, що різними назвами заголовків C vs 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

3
Це досить незвично в багатьох проектах C ++. .h файли використовуються для дуже un-C'ish матеріалів.
einpoklum

4
@einpoklum: Звичайно. Але я намагаюся уникати поведінки "Monkey See Monkey Do". У поточному випадку доступні обидва розширення (та інші), тому я намагаюся змусити їх насправді рахувати. Маючи цей контракт з кодом, який надається спільним клієнтам, дуже корисно: кожен (тобто сотні розробників) знає, що ".H" файли повинні використовуватися клієнтами за допомогою компілятора C, тому не помиляйтесь, що може йти туди чи ні. І кожен (включаючи клієнтів) знає, що ".HPP" файли ніколи не намагатимуться бути зручними для С. Всі перемагають.
paercebal

4
@paercebal, тож ви пропонуєте .H замість .h та .HPP над .hpp ?
Geof Sawaya

6
@GeofSawaya: Ні, вибачте. Це звичка. Під час написання статей я використовую розширення у верхньому регістрі, щоб диференціювати файли за їх типом, як-от ".HPP файли". Але розширення фактичних файлів, які знаходяться на моєму жорсткому диску, завжди знаходяться в малому регістрі, навіть в назві немає, як, наприклад, "MyClass.hpp" або "module.hpp"
paercebal

4
Дякую, @paercebal. Я ставав педантичним
Геоф Савейя

48

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

Зазвичай, коли я бачив (і використовую) .hppяк розширення, відповідного .cppфайлу немає . Як говорили інші, це правило не є важким і швидким, як я зазвичай використовую .hppфайли.


31

Не має значення, яке розширення ви використовуєте. Або з одним добре.

Я використовую *.hдля C і *.hppдля C ++.


23

EDIT [Додано пропозицію від Dan Nissenbaum]:

За однією умовою, .hpp-файли використовуються, коли прототипи визначені в самому заголовку. Такі визначення в заголовках є корисними у випадку шаблонів, оскільки компілятор генерує код для кожного типу лише для інстанції шаблону. Отже, якщо вони не визначені у файлах заголовків, їх визначення не будуть вирішені під час посилання від інших одиниць компіляції. Якщо ваш проект - це лише C ++ проект, який широко використовує шаблони, ця умова буде корисною.

Деякі бібліотеки шаблонів, які дотримуються цієї конвенції, надають заголовкам розширення .hpp, щоб вказати, що у них немає відповідних .cpp-файлів.

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

Цитата з Boost FAQ,

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


Нічого з цього не відповідає дійсності, це не має значення, чи є файл .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якщо насправді немає причин проти цього.

Оскільки документи ISO / IEC використовують це позначення файлів заголовків, і жодне узгодження рядків .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'символи, і залежно від того, чи потрібно його включити, <>не можна містити >. Або в інший спосіб, якщо він включений через ""-включити його не дозволяється містити ".

Іншими словами: якщо у вас було середовище, яке підтримує назви файлів типу prettyStupidIdea.>, включайте такі:

#include "prettyStupidIdea.>"

буде дійсним, але:

#include <prettyStupidIdea.>>

було б недійсним. Інакше навпаки.

І навіть

#include <<.<>

буде дійсним ім'ям файлу заголовка, що можна включити.

Навіть це відповідало б C++, це було б досить дурною ідеєю, тхо.

І тому .hppсправедливий теж.

Але це не результат комітетів, які розробляють рішення для мови!

Тому обговорювати питання про використання .hpp- це те саме, що робити .cc, .mmабо що я ще читав в інших публікаціях на цю тему.

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

Але це не частина мови.

І кожного разу, коли хтось вирішить використовувати це таким чином. Це може бути тому, що йому це найбільше подобається, або тому, що цього вимагають деякі програми робочого процесу, це ніколи 2 не є вимогою мови. Отже, хто каже "пп тому, що він використовується з C ++", просто помиляється щодо визначення мов.

C ++ дозволяє все, що стосується попереднього абзацу. І якщо є що-небудь, що комітет запропонував використати, то він використовує, .hоскільки це розширення, яке подається у всіх прикладах документа ISO.

Висновок:

Поки ви не бачите / не відчуваєте жодної потреби користуватися .hнад .hppабо навпаки, не варто турбуватися. Тому що обидва будуть формувати дійсне ім'я заголовка однакової якості стосовно стандарту. А отже, все, що ПОТРІБНО Вам використовувати .hабо .hppє додатковим обмеженням стандарту, яке навіть може суперечити іншим додатковим обмеженням, невідповідним один одному. Але оскільки ОП не згадує жодних додаткових мовних обмежень, це єдиний правильний і прийнятний відповідь на питання

" * .h або * .hpp для визначень вашого класу ":

Обидва є однаково правильними та застосовними, доки немає зовнішніх обмежень.


1 З того, що мені відомо, мабуть, саме .hppрозширювальна рамка придумала це розширення.

2 Звичайно, я не можу сказати, що принесуть деякі майбутні версії!


7

Я вважаю за краще .hpp для C ++, щоб зрозуміти як редакторам, так і іншим програмістам, що це заголовок C ++, а не файл заголовка C.


6

C ++ ("C Plus Plus") має сенс як .cpp

Маючи файли заголовка з розширенням .hpp не мають однакового логічного потоку.


6

Ви можете зателефонувати своїм включеним, що завгодно.

Просто потрібно вказати це повне ім'я в #include.

Я пропоную, якщо ви працюєте з C, .hа коли з C ++ .hpp.

Це врешті-решт просто умовність.


5

Codegear C ++ Builder використовує .hpp для файлів заголовків, що автоматично генеруються з вихідних файлів Delphi, та .h файлів для ваших "власних" файлів заголовків.

Отже, коли я пишу заголовок C ++, я завжди використовую .h.


5

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


5

Bjarne Stroustrup та Herb Sutter мають відповідь на це запитання у своїх основних керівних принципах 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.


4

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

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


3

На щастя, це просто.

Ви повинні використовувати .hpp розширення, якщо ви працюєте з C ++, і ви повинні використовувати .h для C або змішування C і C ++.


2

Я використовую .h, оскільки саме цим користується Microsoft, і що створює їх генератор коду. Не потрібно йти проти зерна.


не скрізь, у багатьох прикладах (eq WINDDK) вони використовують .hpp
-wiggle

13
Я б не назвав Microsoft "зерном", коли йдеться про C ++.
developerbmw

@Brett це коли твоя робота. І навіть якщо це не так, це проклятий популярний компілятор.
Марк Викуп

@MarkRansom Я більше посилався на історію використання Microsoft Microsoft. IMO VC ++ - відмінний компілятор.
developerbmw

1
@developerbmw Я б сказав, що MSVC - це зерно для програм Windows, а GCC - це зерно для програм * nix, особисто. Наскільки мені відомо, вони більшість інших компіляторів для цих платформ намагаються залишатися сумісними.
Час Джастіна - Відновіть Моніку

1

У "Мові програмування на C ++, третє видання Б'ярна Струструпа", nº1 обов'язково читає книгу C ++, він використовує * .h. Тож я припускаю, що найкращою практикою є використання * .h.

Однак * .hpp також добре!


1
Якщо хтось написав книгу про щось, чого він дізнався від інших, хто навчився її з іншої (можливо, з долею того ж) книги, написаної тим, хто, можливо, мав першоджерело в наявності, то це те, що вони роблять що завгодно, але не знак для найкраща практика.
dhein

Тільки кажучи: я насправді спростував цього. Але я б схвалив це, якби в ньому було написано "ISO / IEC N3690" або будь-який інший проект "C ++", який є "мовою програмування на C ++, третє видання Bjarne Stroustrup". Хоча це було б справедливим моментом, оскільки мова про .hppцю мову зовсім не згадується .
dhein

9
@zaibis ви знаєте, що Bjarne Stroustrup винайшов C ++ так?
tumtumtum

@tumtumtum: захоплювався, я про це не знав. Але в будь-якому випадку, навіть у такому випадку, це все-таки документ комітету, підтримуючи стандарт, який потрібно приймати. Навіть якщо він винахідник мови, це вже не його рішення. Отже, хоча це робить цю відповідь більш неоднозначною, все ж таки не є вагомим міркуванням.
дехін

1

Інструменти та люди легко щось розмежовують . Це воно.

У звичайному використанні (шляхом підвищення та ін.), .hppЦе заголовки C ++. З іншого боку, .hдля не-C ++ - лише заголовки (переважно C). Точно виявити мову вмісту, як правило, важко, оскільки існує багато нетривіальних випадків, тому ця різниця часто робить готовий до використання інструмент легким для запису. Для людей, як тільки отримаєте умову, вона також легко запам'ятовується та проста у використанні.

Однак зазначу, що сама конвенція не завжди працює, як очікувалося.

  • Це не вимушене специфікацією мов , ані С, ані С ++. Існує багато проектів, які не відповідають конвенції. Після того, як вам потрібно злити їх (змішати), це може викликати клопоти.
  • .hppсам по собі - не єдиний вибір. Чому ні .hhчи .hxx? (Хоча як би там не було, вам зазвичай потрібно принаймні одне звичайне правило про назви файлів та шляхи.)

Я особисто використовую як .hі .hppв моїх проектах C ++. Я не дотримуюся вищезгаданої конвенції, оскільки:

  • Мови, які використовуються в кожній частині проектів, чітко задокументовані. Немає шансів змішати C і C ++ в одному модулі (каталозі). Кожна бібліотека третьої сторони повинна відповідати цьому правилу.
  • Відповідні специфікації мови та дозволені мовні діалекти, що використовуються проектами, також задокументовані. (Насправді я навіть документую джерело стандартних функцій та виправлення помилок (у мовному стандарті), які використовуються .) Це дещо важливіше, ніж розрізняти використовувані мови, оскільки це занадто схильне до помилок і вартість тесту (наприклад, сумісність компілятора) може бути суттєвою (складною і трудомісткою), особливо в проекті, який вже майже в чистому C ++. Назви файлів занадто слабкі, щоб впоратися з цим.
  • Навіть для того ж діалекту С ++ можуть бути важливіші властивості, що підходять до різниці. Наприклад, див. Конвенцію нижче.
  • Назви файлів - це фактично фрагменти крихких метаданих. Порушення конвенції виявити не так просто. Щоб стабільно працювати зі змістом, інструмент з часом повинен залежати не лише від імен. Різниця між розширеннями - лише натяк. Не слід очікувати, що інструменти, які використовують його, постійно поводяться однаково, наприклад, виявлення мови .hфайлів на github.com. (У коментарях може бути щось на зразок shebang, щоб ці вихідні файли були кращими метаданими, але це навіть не звичайно, як назви файлів, тому також не є надійними в цілому.)

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


0

Розширення вихідного файлу може мати значення для вашої системи збирання, наприклад, ви могли б мати правила у вашому Makefile для .cppабо .cфайлів, або ваш компілятор (наприклад , Microsoft cl.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для "заголовка з усіма функціями, визначеними в рядку".

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.