Поскольку я создал файлы .cpp, а затем перенес их в файлы .h, единственная разница, которую я могу найти, заключается в том, что вы не можете #include файлы .cpp. Есть ли разница, которую я упускаю?
В чем разница между файлом .cpp и файлом .h?
Ответы (8)
Система сборки C++ (компилятор) не знает разницы, так что это все одно из соглашений.
По соглашению файлы .h являются объявлениями, а файлы .cpp — определениями.
Вот почему файлы .h включаются #include — мы включаем объявления.
Файл .cpp является единицей компиляции: это реальный файл исходного кода, который будет скомпилирован (на C++).
Файлы .h (заголовки) — это файлы, которые будут виртуально копироваться/вставляться в файлы .cpp, где появляется инструкция прекомпилятора #include. После вставки кода заголовков в код .cpp можно начинать компиляцию .cpp.
Заголовочный файл (.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
.
Файлы .h или файлы заголовков используются для перечисления общедоступных переменных экземпляра и методов в объявлении класса. Файлы .cpp или файлы реализации используются для фактической реализации этих методов и использования этих переменных экземпляра.
Причина, по которой они разделены, заключается в том, что файлы .h не компилируются в двоичный код, в то время как файлы .cpp компилируются. Возьмем, к примеру, библиотеку. Скажите, что вы автор, и вы не хотите, чтобы это было с открытым исходным кодом. Таким образом, вы распространяете скомпилированную двоичную библиотеку и файлы заголовков среди своих клиентов. Это позволяет им легко видеть всю информацию о классах вашей библиотеки, которую они могут использовать, не имея возможности видеть, как вы реализовали эти методы. Они больше для людей, использующих ваш код, а не для компилятора. Как было сказано ранее: это условность.
Я знаю разницу между объявлением и определением.
В то время как:
- Файл CPP включает определения из любого заголовка, который он включает (поскольку файл CPP и файл заголовка вместе становятся единой «единицей перевода»).
- Файл заголовка может быть включен более чем в один файл CPP.
- Компоновщику обычно не нравится что-либо, определенное более чем в одном файле CPP.
Поэтому любые определения в заголовочном файле должны быть встроенными или статическими. Файлы заголовков также содержат объявления, которые используются более чем одним файлом CPP.
Определения, которые не являются ни статическими, ни встроенными, помещаются в файлы CPP. Кроме того, любые объявления, которые необходимы только в одном файле CPP, часто размещаются в самом файле CPP, а не в каком-либо (общедоступном) заголовочном файле.
Хорошее эмпирическое правило: «Файлы .h должны иметь объявления [потенциально], используемые несколькими исходными файлами, но не запускаемый код».
Другие уже предложили хорошие объяснения, но я подумал, что должен прояснить различия между различными расширениями:
Source Files for C: .c Header Files for C: .h Source Files for C++: .cpp Header Files for C++: .hpp
Конечно, как уже отмечалось, это всего лишь условности. Компилятор на самом деле не обращает на них никакого внимания - это чисто для удобства кодера.
По соглашению файлы .h включаются в другие файлы и никогда не компилируются сами по себе. Файлы .cpp - опять же, по соглашению - корни процесса компиляции; они прямо или косвенно включают файлы .h, но обычно не файлы .cpp.