Включить директивы в заголовочный файл?

Возможный дубликат:
где «включить» следует поместить в C ++

Очевидно, что есть две «школы мысли» о том, стоит ли #include директивы в заголовочные файлы C ++ (или, в качестве альтернативы, положить #include только в файлы cpp). Некоторые люди говорят, что все в порядке, другие говорят, что это только вызывает проблемы. Кто-нибудь знает, пришел ли этот разговор к выводу, что следует отдавать предпочтение?

3

Решение

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

6

Другие решения

То, что я нашел эффективным, следует нескольким простым правилам

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

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

3

Как правило, вы не включаете заголовки в заголовок, если там требуется их полное определение. Большую часть времени вы играете с указателями классов в заголовочном файле, так что будет просто объявить их там.

2

Я думаю, что проблема была решена давным-давно: заголовки должны быть автономными (то есть не должно зависеть от того, что пользователь включил другие заголовки раньше — этот аспект исчерпан так долго, что некоторые даже не осознают, что спор об этом, но ваш положить включает только в .cpp кажется, намекает на это), но минимальный (то есть не должен включать определения, когда декларации будет достаточно для самодостаточности).

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

1

Это не столько школы мысли, сколько религии. На самом деле, оба подхода имеют свои преимущества и недостатки, и существуют определенные практики, которым необходимо следовать, чтобы любой подход был успешным. Но только один из этих подходов «масштабируется» до крупных проектов.

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

Однако эту практику трудно поддерживать, особенно в больших проектах со многими программистами. Это довольно неудобно, когда вы хотите использовать модуль foo, но вы не можете просто #include "foo.h": вам нужно включить 35 других заголовков.

В итоге происходит следующее: программисты не собираются тратить свое время на поиск точного, минимального набора заголовков, который им нужен просто для добавления модуля. foo, Чтобы сэкономить время, они пойдут к какому-нибудь исходному файлу примера, подобному тому, над которым они работают, и вырежут и вставят все #include директивы. Затем они попытаются скомпилировать его, и если он не скомпилируется, то они будут вырезать и вставлять больше #include директивы еще из другого места, и повторять это, пока он не работает.

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

Как только каждый исходный файл включает в себя почти каждый заголовок, вы можете также иметь большой everything.h который включает в себя все заголовки, а затем #include "everything.h" в каждом исходном файле.

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

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector