Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
[Alexandrescu01] §3 • [Boost] • [Gamma95] • [Lakos96] §0.2.1, §4.6-14, §5 • [Martin96a] • [Martin96b] • [Martin98] §7 • [Martin00] • [McConnell93] §5 • [Meyers97] §46 • [Stroustrup00] §24.3.5 • [Sutter00] §26 • [Sutter02] §37 • [Sutter03]
23. Делайте заголовочные файлы самодостаточными
Убедитесь, что каждый написанный вами заголовочный файл компилируем самостоятельно, т.е. что он включает все заголовочные файлы, от которых зависит его содержимое.
Если один заголовочный файл не работает, пока не включен другой заголовочный файл, проект получается очень
Раньше некоторые эксперты советовали, чтобы заголовочные файлы не включали другие заголовочные файлы из-за накладных расходов на многократное открытие и анализ заголовочных файлов, защищенных директивами препроцессоров от повторной обработки. К счастью, сейчас этот совет устарел. Многие современные компиляторы С++ распознают соответствующую защиту заголовочных файлов автоматически (см. рекомендацию 24) и просто не открывают один и тот же заголовочный файл дважды. Некоторые компиляторы используют предкомпиляцию заголовочных файлов, которая позволяет избежать анализа часто используемых заголовочных файлов.
Однако не включайте заголовочные файлы, в которых вы не нуждаетесь, так как это напрасно создает паразитные зависимости.
Для гарантии самодостаточности заголовочных файлов скомпилируйте каждый из них отдельно от других и убедитесь, что это не приводит к ошибкам или предупреждениям.
Ряд тонких моментов возникает в связи с использованием шаблонов.
Пример 1. Зависимые имена. Шаблоны компилируются в точке, где они определены, с тем исключением, что все зависимые имена или типы не компилируются до точки инстанцирования. Это означает, что
Пример 2. Шаблоны функций-членов и функции-члены шаблонов инстанцируются только при использовании. Предположим, что
[Lakos96] §3.2 • [Stroustrup00] §9.2.3 • [Sutter00] §26-30 • [Vandevoorde03] §9-10
24. Используйте только внутреннюю, но не внешнюю защиту директивы
Предотвращайте непреднамеренное множественное включение ваших заголовочных файлов директивой
Каждый заголовочный файл должен использовать внутреннюю защиту директивы
Обратите внимание на следующие правила при определении защиты включения.
• Используйте для защиты уникальные имена. Убедитесь, что вы используете имена, уникальные, по крайней мере, в пределах вашего приложения. Выше мы использовали одно распространенное соглашение для используемых в защите имен; имена для защиты могут включать имя приложения, а некоторые инструменты генерируют имена для защиты, содержащие случайные числа.
• Не пытайтесь хитрить. Не размещайте никакого кода или комментариев до и после защищенной части, и следуйте показанной выше стандартной форме защиты. Современные препроцессоры могут обнаружить защиту, но могут оказаться малоинтеллектуальными и ожидать кода защиты строго в начале и в конце заголовочных файлов.
Избегайте использования устаревшей внешней защиты директивы
Внешняя защита утомительна, устарела для современных компиляторов и ненадежна из-за необходимости согласования имен для защиты.
В очень редких случаях заголовочный файл может быть предназначен для многократного включения.
[C++03, §2.1] • [Stroustrup00] §9.3.3
Функции и операторы
Если ваша процедура имеет десять параметров — вероятно, вы где-то ошиблись.
Функции, включая перегруженные операторы, представляют собой фундаментальные единицы работы. Как вы увидите позже в разделе "Обработка ошибок и исключения" (в частности, в рекомендации 70), это непосредственно влияет на наши рассуждения о корректности и безопасности кода.
Но давайте сначала рассмотрим некоторые фундаментальные вопросы написания функций, в том числе операторов. В частности, мы обратим особое внимание на их параметры, семантику и перегрузку.
В этом разделе наиболее важной нам представляется рекомендация 26 — "Сохраняйте естественную семантику перегруженных операторов".
25. Передача параметров по значению, (интеллектуальному) указателю или ссылке
Вы должны четко уяснить разницу между входными, выходными параметрами и параметрами, предназначенными и для ввода, и для вывода информации, а также между передачей параметров по значению и по ссылке, и корректно их использовать.
Правильный выбор способа передачи аргументов в функцию — по значению, ссылке или с использованием указателей — весьма необходимый навык, который поможет вам сделать ваш код максимально безопасным и эффективным.
Хотя эффективность не должна быть нашей главной целью (см. рекомендацию 8), при прочих равных условиях, включая понятность кода, мы не должны без крайней необходимости снижать его эффективность (см. рекомендацию 9).
Вам стоит следовать приведенным ниже рекомендациям при выборе способа передачи параметров. Вот рекомендации для входных параметров (которые передают информацию в функцию, но не возвращают ее).