Пример 1. Зависимые имена. Шаблоны компилируются в точке, где они определены, с тем исключением, что все зависимые имена или типы не компилируются до точки инстанцирования. Это означает, что template class Widget с членом std::deque не приведет к ошибке времени компиляции, даже если заголовочный файл не включен — если при этом не происходит инстанцирование Widget. Поскольку очевидно, что шаблон Widget существует для того, чтобы быть инстанцированным, его заголовочный файл должен содержать строку #include .

Пример 2. Шаблоны функций-членов и функции-члены шаблонов инстанцируются только при использовании. Предположим, что Widget не имеет члена типа std::deque, но функция-член Widget с именем Transmogrify использует deque. Тогда вызывающая Widget функция может инстанцировать и использовать Widget, даже если заголовочный файл не включен — до тех пор, пока не используется функция-член Transmogrify. По умолчанию заголовочный файл Widget все же должен включать , поскольку это необходимо, по крайней мере, для некоторых пользователей Widget. В редких случаях, когда большой заголовочный файл включается только для обеспечения работоспособности нескольких редко используемых функций шаблона, следует подумать о том, чтобы сделать эти функции не членами и вынести их в отдельный заголовочный файл, включающий упомянутый большой файл (см. рекомендацию 44).

Ссылки

[Lakos96] §3.2 • [Stroustrup00] §9.2.3 • [Sutter00] §26-30 • [Vandevoorde03] §9-10

<p>24. Используйте только внутреннюю, но не внешнюю защиту директивы <code>#include</code></p>Резюме

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

Обсуждение

Каждый заголовочный файл должен использовать внутреннюю защиту директивы #include, чтобы предотвратить переопределения в случае множественного включения данного файла. Например, заголовочный файл fоо.h должен иметь такой общий вид:

#ifndef FOO_H_INCLUDED_

#define FOO_H_INCLUDED_

// ... Содержимое файла …

#endif

Обратите внимание на следующие правила при определении защиты включения.

Используйте для защиты уникальные имена. Убедитесь, что вы используете имена, уникальные, по крайней мере, в пределах вашего приложения. Выше мы использовали одно распространенное соглашение для используемых в защите имен; имена для защиты могут включать имя приложения, а некоторые инструменты генерируют имена для защиты, содержащие случайные числа.

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

Избегайте использования устаревшей внешней защиты директивы #include, рекомендуемой в некоторых старых книгах:

#ifndef FOO_H_INCLUDED_ // не рекомендуется

#include "foo.h"

#define FOO_H_INCLUDED_

#endif

Внешняя защита утомительна, устарела для современных компиляторов и ненадежна из-за необходимости согласования имен для защиты.

Исключения

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

Ссылки

[C++03, §2.1] • [Stroustrup00] §9.3.3

<p>Функции и операторы</p>

Если ваша процедура имеет десять параметров — вероятно, вы где-то ошиблись.

— Алан Перлис (Alan Perlis)

Функции, включая перегруженные операторы, представляют собой фундаментальные единицы работы. Как вы увидите позже в разделе "Обработка ошибок и исключения" (в частности, в рекомендации 70), это непосредственно влияет на наши рассуждения о корректности и безопасности кода.

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

В этом разделе наиболее важной нам представляется рекомендация 26 — "Сохраняйте естественную семантику перегруженных операторов".

<p>25. Передача параметров по значению, (интеллектуальному) указателю или ссылке</p>Резюме
Перейти на страницу:

Все книги серии C++ In-Depth

Похожие книги