На самом деле в C ++ это несколько сложнее, чем в организации заголовка C / источника.
Что видит компилятор?
Компилятор видит один большой исходный файл (.cpp) с правильно включенными заголовками. Исходный файл - это модуль компиляции, который будет скомпилирован в объектный файл.
Итак, зачем нужны заголовки?
Поскольку одному модулю компиляции может потребоваться информация о реализации в другом модуле компиляции. Таким образом, можно написать, например, реализацию функции в одном источнике, и написать объявление этой функции в другом источнике, нуждающемся в ее использовании.
В этом случае есть две копии одной и той же информации. Что является злом ...
Решение - поделиться некоторыми деталями. Хотя реализация должна оставаться в Source, объявление общих символов, таких как функции, или определение структур, классов, перечислений и т. Д. Может потребоваться для совместного использования.
Заголовки используются для размещения этих общих сведений.
Переместить в заголовок объявления о том, что необходимо разделить между несколькими источниками
Ничего больше?
В 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.
Вау!
В «реальной жизни» это обычно менее сложно. Большая часть кода будет иметь только простую организацию заголовка / исходного кода с некоторым встроенным кодом в исходном коде.
Но в других случаях (объекты-шаблоны, зная друг друга), мне приходилось иметь для каждого объекта отдельные объявления и заголовки реализации с пустым источником, включая эти заголовки, просто чтобы помочь мне увидеть некоторые ошибки компиляции.
Другой причиной разбиения заголовков на отдельные заголовки может быть ускорение компиляции, ограничение количества разбираемых символов до необходимого и избегание ненужной перекомпиляции источника, который заботится только о предварительном объявлении при реализации встроенного метода. измененное.
Заключение
Вы должны сделать свою организацию кода как можно более простой и максимально модульной. Положите как можно больше в исходном файле. Выставляйте только в заголовках то, что нужно разделить.
Но в тот день, когда вы будете иметь круговую зависимость между шаблонными объектами, не удивляйтесь, если ваша организация кода станет несколько более "интересной", чем простая организация заголовка / источника ...
^ _ ^