template
с членом std::deque
не приведет к ошибке времени компиляции, даже если заголовочный файл
не включен — если при этом не происходит инстанцирование Widget
. Поскольку очевидно, что шаблон Widget
существует для того, чтобы быть инстанцированным, его заголовочный файл должен содержать строку #include
.
Widget
не имеет члена типа std::deque
, но функция-член Widget
с именем Transmogrify
использует deque
. Тогда вызывающая Widget
функция может инстанцировать и использовать Widget
, даже если заголовочный файл
не включен — до тех пор, пока не используется функция-член Transmogrify
. По умолчанию заголовочный файл Widget
все же должен включать
, поскольку это необходимо, по крайней мере, для некоторых пользователей Widget
. В редких случаях, когда большой заголовочный файл включается только для обеспечения работоспособности нескольких редко используемых функций шаблона, следует подумать о том, чтобы сделать эти функции не членами и вынести их в отдельный заголовочный файл, включающий упомянутый большой файл (см. рекомендацию 44).
24. Используйте только внутреннюю, но не внешнюю защиту директивы #include
Предотвращайте непреднамеренное множественное включение ваших заголовочных файлов директивой #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
Внешняя защита утомительна, устарела для современных компиляторов и ненадежна из-за необходимости согласования имен для защиты.
В очень редких случаях заголовочный файл может быть предназначен для многократного включения.
Функции и операторы
Если ваша процедура имеет десять параметров — вероятно, вы где-то ошиблись.
Функции, включая перегруженные операторы, представляют собой фундаментальные единицы работы. Как вы увидите позже в разделе "Обработка ошибок и исключения" (в частности, в рекомендации 70), это непосредственно влияет на наши рассуждения о корректности и безопасности кода.
Но давайте сначала рассмотрим некоторые фундаментальные вопросы написания функций, в том числе операторов. В частности, мы обратим особое внимание на их параметры, семантику и перегрузку.
В этом разделе наиболее важной нам представляется рекомендация 26 — "Сохраняйте естественную семантику перегруженных операторов".
25. Передача параметров по значению, (интеллектуальному) указателю или ссылке