В чем разница между файлом .cpp и файлом .h?

Поскольку я создал файлы .cpp, а затем перенес их в файлы .h, единственная разница, которую я могу найти, заключается в том, что вы не можете #include файлы .cpp. Есть ли разница, которую я упускаю?


person Community    schedule 17.05.2009    source источник
comment
Чтобы понять ответы людей ниже, вам может потребоваться задать другой вопрос: т. Е. В чем разница между «декларацией» и «определением» в C++?   -  person ChrisW    schedule 18.05.2009
comment
Я знаю разницу между объявлением и определением.   -  person    schedule 18.05.2009
comment
Вы можете включать все, что хотите, но этап связывания прервется, если вы включите глобальные переменные в более чем одну единицу компиляции. Вот почему существует соглашение не связывать файлы .cpp.   -  person John Smith    schedule 18.05.2009


Ответы (8)


Система сборки C++ (компилятор) не знает разницы, так что это все одно из соглашений.

По соглашению файлы .h являются объявлениями, а файлы .cpp — определениями.

Вот почему файлы .h включаются #include — мы включаем объявления.

person Macker    schedule 17.05.2009
comment
Система сборки C++ различается — попробуйте запустить g++ для файла .h и файла .cpp и посмотрите, что произойдет, например. - person ; 18.05.2009
comment
Я знаю, что файлы .cpp используются (в большинстве случаев) для определения функций/классов/и т. д., которые были объявлены в файлах .h, но вы также можете определять переменные в файлах .h. - person ; 18.05.2009
comment
@Neil Butterworth: Да, компилятор G++ понимает соглашение, но вы можете заставить его скомпилироваться, заставив язык. - person Martin York; 18.05.2009

Файл .cpp является единицей компиляции: это реальный файл исходного кода, который будет скомпилирован (на C++).

Файлы .h (заголовки) — это файлы, которые будут виртуально копироваться/вставляться в файлы .cpp, где появляется инструкция прекомпилятора #include. После вставки кода заголовков в код .cpp можно начинать компиляцию .cpp.

person Klaim    schedule 17.05.2009
comment
Почему вы говорите файл .cpp, а не файл .cpp? - person ; 18.05.2009
comment
@Keand64: Потому что компилятор просматривает только один файл .cpp за раз при компиляции. Он читает файл .cpp, читает все включенные файлы .h, компилирует все это, записывает файл .o (или .obj), а затем переходит к следующему файлу .cpp. - person Greg Hewgill; 18.05.2009
comment
Означает ли это, что .cpp и .h должны иметь одно и то же имя? - person fathergorry; 28.02.2020
comment
@fathergorry Нет, нет правил именования исходных файлов (заголовки или нет), только соглашения. - person Klaim; 09.03.2020

Заголовочный файл (.h, .hpp, ...) содержит

  • Определения классов ( class X { ... }; )
  • Определения встроенных функций ( inline int get_cpus() { ... } )
  • Объявления функций ( void help(); )
  • Объявления объектов ( extern int debug_enabled; )

Исходный файл (.c, .cpp, .cxx) содержит

  • Определения функций ( void help() { ... } или void X::f() { ... } )
  • Определения объектов ( int debug_enabled = 1; )

Однако соглашение о том, что заголовки именуются с суффиксом .h, а исходные файлы имеют суффикс .cpp, на самом деле не требуется. Всегда можно указать хорошему компилятору, как обрабатывать какой-либо файл, независимо от его суффикса имени файла ( -x <file-type> для gcc. Например, -x c++ ).

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

person Johannes Schaub - litb    schedule 17.05.2009

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

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

person Marc W    schedule 17.05.2009
comment
Я знаю, что он не спросил, почему, но это самый полезный ответ для меня. понимание почему облегчает подключение логики к деталям - person vampiire; 18.04.2020

Я знаю разницу между объявлением и определением.

В то время как:

  • Файл CPP включает определения из любого заголовка, который он включает (поскольку файл CPP и файл заголовка вместе становятся единой «единицей перевода»).
  • Файл заголовка может быть включен более чем в один файл CPP.
  • Компоновщику обычно не нравится что-либо, определенное более чем в одном файле CPP.

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

Определения, которые не являются ни статическими, ни встроенными, помещаются в файлы CPP. Кроме того, любые объявления, которые необходимы только в одном файле CPP, часто размещаются в самом файле CPP, а не в каком-либо (общедоступном) заголовочном файле.

person ChrisW    schedule 17.05.2009

Хорошее эмпирическое правило: «Файлы .h должны иметь объявления [потенциально], используемые несколькими исходными файлами, но не запускаемый код».

person dj_segfault    schedule 17.05.2009
comment
Так что я предполагаю, что .h сродни интерфейсам С# - person Hugo Nava Kopp; 25.03.2020

Другие уже предложили хорошие объяснения, но я подумал, что должен прояснить различия между различными расширениями:

  Source Files for C: .c
  Header Files for C: .h

  Source Files for C++: .cpp
  Header Files for C++: .hpp

Конечно, как уже отмечалось, это всего лишь условности. Компилятор на самом деле не обращает на них никакого внимания - это чисто для удобства кодера.

person Noldorin    schedule 17.05.2009
comment
Большинство людей на самом деле используют .h и для C++. - person Zifre; 18.05.2009
comment
@Zifre: Да, поэтому я говорю, что это рекомендуемые соглашения об именах, хотя многие могут им не следовать. - person Noldorin; 18.05.2009

По соглашению файлы .h включаются в другие файлы и никогда не компилируются сами по себе. Файлы .cpp - опять же, по соглашению - корни процесса компиляции; они прямо или косвенно включают файлы .h, но обычно не файлы .cpp.

person bdonlan    schedule 17.05.2009