Что нужно делать в файле .h?

Когда вы делите код на несколько файлов, что именно должно идти в файл .h и что нужно делать в .cpp файле?

Ответ 1

Заголовочные файлы (.h) предназначены для предоставления информации, которая потребуется в нескольких файлах. Такие вещи, как объявления классов, прототипы функций и перечисления, обычно входят в заголовочные файлы. Одним словом, "определения".

Файлы кода (.cpp) предназначены для предоставления информации о реализации, которая должна быть известна только в одном файле. В общем, тела функций и внутренние переменные, которые должны/никогда не будут доступны другими модулями, принадлежат к файлам .cpp. Одним словом, "реализация".

Самый простой вопрос: попросить себя определить, что принадлежит где "если я это изменил, мне нужно будет изменить код в других файлах, чтобы снова скомпилировать?" Если ответ "да", он, вероятно, принадлежит файлу заголовка; если ответ "нет", он, вероятно, принадлежит к файлу кода.

Ответ 2

Фактически, на С++ это несколько сложнее, чем организация заголовка/источника C.

Что видит компилятор?

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

Итак, зачем нужны заголовки?

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

В этом случае есть две копии одной и той же информации. Это зло...

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

Заголовки используются для размещения этих общих сведений.

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

Ничего больше?

В С++ есть другие вещи, которые могут быть помещены в заголовок, потому что они также должны быть разделены:

  • встроенный код
  • Шаблоны
  • константы (обычно те, которые вы хотите использовать внутри переключателей...)

Перейдите в заголовок ВСЕ, что нужно для совместного использования, включая общие реализации

Значит ли это, что в заголовках могут быть источники?

Да. На самом деле, существует много разных вещей, которые могут быть внутри "заголовка" (т.е. Между источниками).

  • Переслать декларацию
  • объявления/определение функций /structs/classes/templates
  • реализация встроенного и шаблонного кода

Он становится сложным, а в некоторых случаях (круговыми зависимостями между символами) невозможно сохранить его в одном заголовке.

Заголовки можно разбить на три части

Это означает, что в крайнем случае вы могли бы:

  • заголовок прямого объявления
  • заголовок объявления/определения
  • заголовок реализации
  • источник реализации

Предположим, у нас есть шаблонный 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.

Wow!

В "реальной жизни" он обычно менее сложный. У большинства кодов будет только простая организация заголовка/источника, с некоторым встроенным кодом в источнике.

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

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

Заключение

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

Но в тот день, когда у вас будут круговые зависимости между шаблонами объектов, не удивляйтесь, если ваша организация кода становится несколько более "интересной", что простая организация заголовка/источника...

^ _ ^

Ответ 3

в дополнение ко всем другим ответам, я расскажу вам, что вы НЕ помещаете в заголовочный файл:
Объявление using (наиболее распространенное из using namespace std;) не должно появляться в файле заголовка, поскольку они загрязняют пространство имен исходного файла, в который оно включено.

Ответ 4

Что компилируется в ничего (нулевой двоичный след) попадает в заголовочный файл.

Переменные не компилируются в ничего, но декларации типа do (поскольку они описывают только поведение переменных).

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

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

Ответ 5

В общем, вы помещаете объявления в файл заголовка и определения в файл реализации (.cpp). Исключением для этого являются шаблоны, где определение должно также идти в заголовке.

Этот вопрос и те, схожие с ним, часто задавались на SO - см. Зачем нужны файлы заголовков и .cpp файлы на С++? и Файлы заголовков С++, разделение кода, например.

Ответ 6

Объявления классов и функций плюс документация, а также определения встроенных функций/методов (хотя некоторые предпочитают помещать их в отдельные .INL файлы).

Ответ 7

В основном заголовочный файл содержит скелет класса или объявление (не меняется часто)

и cpp файл содержит реализацию класса (часто меняются).

Ответ 8

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

в .h

    class Foo {
    int j;

    Foo();
    Foo(int)
    void DoSomething();
}

Ответ 9

Я ожидаю увидеть:

  • декларация
  • комментарии
  • определения, помеченные inline
  • Шаблоны

действительно ответ, хотя это то, что нельзя вставить:

  • definitons (может привести к тому, что вещи будут размножаться)
  • использование деклараций/директив (заставляет их на всех, включая ваш заголовок, может вызывать nameclashes)

Ответ 10

Заголовок (.h)

  • Макросы и включают необходимые для интерфейсов (как можно меньше)
  • Объявление функций и классов
  • Документация на интерфейс
  • Объявление встроенных функций/методов, если есть
  • extern для глобальных переменных (если есть)

Тело (.cpp)

  • Остальные макросы и включает
  • Включить заголовок модуля
  • Определение функций и методов
  • Глобальные переменные (если есть)

Как правило, вы помещаете "общую" часть модуля в .h(часть, которую должны видеть другие модули) и "не общая" часть на .cpp

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

EDIT: Изменено после комментария Дэвида

Ответ 11

Заголовок Определяет, но ничего не сообщает об этой реализации. (Исключая шаблоны в этом "метафоре".

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

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

Теперь я, конечно, говорю о первой подгруппе.

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

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

Ответ 12

  • Заголовочные файлы - не должны меняться во время разработки слишком часто → вам следует подумать и написать их сразу (в идеальном случае)
  • Исходные файлы - изменения во время реализации