При разделении кода на несколько файлов, что именно должно помещаться в файл .h, а что - в файл .cpp?
c++
header-files
Энрико Тувера-младший
источник
источник
.hpp
файл, а объявления C - в.h
файл. Это очень полезно при смешивании кода C и C ++ (например, унаследованных модулей в C).Ответы:
Заголовочные файлы (
.h
) предназначены для предоставления информации, которая потребуется в нескольких файлах. Такие вещи, как объявления классов, прототипы функций и перечисления, обычно помещаются в файлы заголовков. Одним словом, «определения».Файлы кода (
.cpp
) предназначены для предоставления информации о реализации, которая должна быть известна только в одном файле. В общем, тела функций и внутренние переменные, которые не должны / никогда не должны быть доступны другим модулям, принадлежат.cpp
файлам. Одним словом, «реализации».Самый простой вопрос, который нужно задать себе, чтобы определить, что принадлежит и где находится: «Если я изменю это, мне придется изменить код в других файлах, чтобы снова компилировать вещи?» Если ответ «да», он, вероятно, принадлежит заголовочному файлу; если ответ «нет», он, вероятно, принадлежит файлу кода.
источник
export
). Единственный способ обойти №1 - это PIMPL. # 2 был бы возможен, если быexport
поддерживался, и может быть возможно с использованием c ++ 0x иextern
шаблонов. IMO, файлы заголовков в С ++ теряют большую часть своей полезности.Дело в том, что в C ++ это несколько сложнее, чем организация заголовка / источника C.
Что видит компилятор?
Компилятор видит один большой исходный файл (.cpp) с правильно включенными заголовками. Исходный файл - это единица компиляции, которая будет скомпилирована в объектный файл.
Итак, зачем нужны заголовки?
Потому что одному модулю компиляции может потребоваться информация о реализации в другом модуле компиляции. Таким образом, можно написать, например, реализацию функции в одном источнике и написать объявление этой функции в другом источнике, в котором необходимо ее использовать.
В этом случае есть две копии одной и той же информации. Что зло ...
Решение - поделиться некоторыми подробностями. Хотя реализация должна оставаться в источнике, объявление общих символов, таких как функции, или определение структур, классов, перечислений и т. Д., Может потребоваться совместно.
Заголовки используются для размещения этих общих деталей.
Переместите в заголовок объявления о том, что нужно разделить между несколькими источниками
Ничего более?
В C ++ есть и другие вещи, которые можно поместить в заголовок, потому что они тоже должны быть общими:
Переместите в заголовок ВСЕ, чем нужно поделиться, включая общие реализации
Значит ли это, что внутри заголовков могут быть источники?
Да. На самом деле, есть много разных вещей, которые могут быть внутри «заголовка» (т. Е. Разделены между источниками).
Это становится сложным, а в некоторых случаях (циклические зависимости между символами) невозможно сохранить его в одном заголовке.
Заголовки можно разбить на три части
Это означает, что в крайнем случае у вас могут быть:
Представим, что у нас есть шаблонный объект MyObject. У нас могло быть:
// - - - - MyObject_forward.hpp - - - - // This header is included by the code which need to know MyObject // does exist, but nothing more. template<typename T> class MyObject ;
.
// - - - - MyObject_declaration.hpp - - - - // This header is included by the code which need to know how // MyObject is defined, but nothing more. #include <MyObject_forward.hpp> template<typename T> class MyObject { public : MyObject() ; // Etc. } ; void doSomething() ;
.
// - - - - MyObject_implementation.hpp - - - - // This header is included by the code which need to see // the implementation of the methods/functions of MyObject, // but nothing more. #include <MyObject_declaration.hpp> template<typename T> MyObject<T>::MyObject() { doSomething() ; } // etc.
.
// - - - - MyObject_source.cpp - - - - // This source will have implementation that does not need to // be shared, which, for templated code, usually means nothing... #include <MyObject_implementation.hpp> void doSomething() { // etc. } ; // etc.
Вот это да!
В «реальной жизни» это обычно не так сложно. Большая часть кода будет иметь только простую организацию заголовка / источника с некоторым встроенным кодом в исходном коде.
Но в других случаях (шаблонные объекты, знающие друг друга) мне приходилось иметь для каждого объекта отдельное объявление и заголовки реализации с пустым источником, включая эти заголовки, просто чтобы помочь мне увидеть некоторые ошибки компиляции.
Еще одна причина разбить заголовки на отдельные заголовки может заключаться в ускорении компиляции, ограничении количества анализируемых символов до необходимого количества и избежании ненужной перекомпиляции источника, который заботится только о прямом объявлении при изменении реализации встроенного метода.
Вывод
Вы должны сделать организацию кода как можно более простой и как можно более модульной. Поместите как можно больше в исходный файл. В заголовках указывайте только то, чем нужно поделиться.
Но в тот день, когда у вас возникнут циклические зависимости между шаблонными объектами, не удивляйтесь, если ваша организация кода станет несколько более "интересной", чем простая организация заголовка / источника ...
^ _ ^
источник
в дополнение ко всем другим ответам я скажу вам, что вы НЕ помещаете в файл заголовка:
using
объявление (наиболее распространенноеusing namespace std;
) не должно появляться в файле заголовка, потому что они загрязняют пространство имен исходного файла, в который он включен .источник
using
для переноса чего-либо в глобальное пространство имен в заголовке.static inline
в C99, потому что что-то связано с тем, что происходит, когда вы объединяете внутреннюю связь с шаблонами. Пространства имен Anon позволяют «скрывать» функции, сохраняя при этом внешнюю связь.То, что компилируется в ничто (нулевой двоичный след), попадает в файл заголовка.
Переменные не компилируются в ничто, но объявления типов делают (потому что они описывают только поведение переменных).
функции нет, но встроенные функции (или макросы) делают это, потому что они создают код только там, где они вызываются.
шаблоны - это не код, это всего лишь рецепт для создания кода. поэтому они также входят в h-файлы.
источник
Как правило, объявления помещаются в файл заголовка, а определения - в файл реализации (.cpp). Исключением являются шаблоны, определение которых также должно быть в заголовке.
Этот и похожие на него вопросы часто задаются в SO - см. Почему в C ++ используются файлы заголовков и файлы .cpp? и файлы заголовков C ++, например , разделение кода .
источник
Объявления ваших классов и функций, а также документация и определения встроенных функций / методов (хотя некоторые предпочитают помещать их в отдельные файлы .inl).
источник
В основном файл заголовка содержит скелет или объявление класса (не часто меняется)
а файл cpp содержит реализацию класса (часто меняется).
источник
файл заголовка (.h) должен быть для объявлений классов, структур и их методов, прототипов и т.д. Реализация этих объектов выполняется в cpp.
в .h
class Foo { int j; Foo(); Foo(int) void DoSomething(); }
источник
Я ожидал увидеть:
на самом деле ответ заключается в том, что не нужно вставлять:
источник
Заголовок что-то определяет, но ничего не говорит о реализации. (За исключением шаблонов в этом "метафоре".
С учетом сказанного, вам нужно разделить «определения» на подгруппы, в данном случае есть два типа определений.
Теперь я, конечно, говорю о первой подгруппе.
Заголовок предназначен для определения макета вашей структуры, чтобы помочь остальной части программного обеспечения использовать реализацию. Возможно, вы захотите увидеть это как «абстракцию» вашей реализации, что шутливо сказано, но я думаю, что в данном случае это вполне подходит.
Как было сказано и показано в предыдущих плакатах, вы объявляете частные и общедоступные области использования и их заголовки, это также включает частные и общедоступные переменные. Я не хочу здесь вдаваться в разработку кода, но вы можете подумать о том, что вы вставляете в свои заголовки, поскольку это уровень между конечным пользователем и реализацией.
источник
источник
Заголовок (.h)
Тело (.cpp)
Как правило, вы помещаете «совместно используемую» часть модуля в .h (часть, которую должны видеть другие модули), а «не разделяемую» часть в .cpp.
ПД: Да, я включил глобальные переменные. Я использовал их несколько раз, и важно не определять их в заголовках, иначе вы получите много модулей, каждый из которых определяет свою собственную переменную.
РЕДАКТИРОВАТЬ: изменено после комментария Дэвида
источник