Я знаю, что это не имеет большого значения для проекта, но, если вы используете #defined защиту заголовков для своего кода на C++, какой формат вы используете? например предполагая, что заголовок называется foo.hpp:
#ifndef __FOO_HPP__
...
#ifndef INCLUDED_FOO_HPP
...
#ifndef SOME_OTHER_FORMAT
Мне нравится идея #define в верхнем регистре, но я не могу остановиться на формате для этих охранников.





Я всегда использую INCLUDED_FOO_HPP
Я бы не стал использовать двойное подчеркивание, потому что начало вещей с двойным подчеркиванием зарезервировано.
я использую
#if !defined(FOO_HPP_INCLUDED)
Я предпочитаю современный синтаксис defined, потому что он позволяет || && операторы, даже если они здесь не используются.
Также
#ifndef __FOO_HPP__
технически незаконно, так как начальные подчеркивания зарезервированы.
Не уверен, что за это проголосовали против. В этом нет ничего плохого, даже если бы я всегда использовал #ifndef вместо! Defined (), потому что нет необходимости использовать || или && в этом контексте.
Я всегда использую
#ifndef FOOBAR_CPP
Если вы используете Visual Studio или компилятор Microsoft, используйте метод прагмы
#pragma once
Наверное, потому, что это непереносимо. Используйте прагму, но также поставьте защиту включения, на тот случай, если вам когда-нибудь понадобится другой компилятор.
потому что такой код заставит вас немедленно провалить собеседование со мной.
проверьте это: learningcppisfun.blogspot.com/2008/02/…
Даже если вы используете Visual Studio, вам все равно следует по возможности придерживаться стандарта.
@KeithB, вопрос по переносимости не задавал.
@Shy, если вы подводите людей к правильным ответам с правильной квалификацией, вам, вероятно, не следует ни с кем брать интервью.
Этот ответ не получит от меня одобрения без дополнительных оговорок и оговорок в тексте. Я не уверен в голосовании против; это заманчиво, но не обязательно.
Если вопрос конкретно не касается решения для конкретной платформы, я всегда предпочитаю портативное решение. Даже если платформа указана, с учетом выбора между переносимой и конкретной платформой, следует отдавать предпочтение переносному решению.
Также поддерживается GCC с 3.4, это не только Microsoft. Конечно, речь идет о предпочтении портативных кодовых стоек.
Обратите внимание, что Microsoft в своих собственных заголовках для VisualC++, которым нужна нулевая переносимость, использует оба стиля защиты.
Чтобы действительно избежать конфликтов имен, я использую GUID:
#ifndef GUARD_8D419A5B_4AC2_4C34_B16E_2E5199F262ED
Это имеет странный смысл :-)
Также можно использовать дату и время - если вы не хотите создавать идентификаторы GUID.
Это работает, но может сбить с толку, если вам нужно проверить включение заголовка в какой-либо файл cpp.
Маловероятно, что в моей системе будет столько включаемых файлов, сколько атомов в известной вселенной - если только у нас нет субатомных жестких дисков.
Я предпочитаю такой формат:
#ifndef FOO_HPP
#define FOO_HPP
/* ... */
#endif // FOO_HPP
MYLIB_FOO_HPP, и это помогает избежать конфликтов имен.Лично я просто использую имя файла FOO_HPP. Google использует весь путь, например SRC_ENGINE_FAST_HPP.
Certain sets of names and function signatures are always reserved to the implementation:
- Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
- Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
(17.4.3.1.2/1)
Я поддерживаю это, за исключением того, что я предпочитаю использовать тот же регистр для #define, что и для имени файла. В среде UNIX (и т. д.) FOO.HPP - это не то же самое, что foo.hpp.
Я всегда включал пространство имен или относительный путь в защиту включения, потому что только имя заголовка оказалось опасным.
Например, у вас есть большой проект с двумя файлами где-то в вашем коде.
/myproject/module1/misc.h
/myproject/module2/misc.h
Так что, если вы используете согласованную схему именования для своих охранников включения, вы можете в конечном итоге получить _MISC_HPP__, определенный в обоих файлах (очень забавно находить такие ошибки).
Итак, я согласился с
MYPROJECT_MODULE1_MISC_H_
MYPROJECT_MODULE2_MISC_H_
Эти имена довольно длинные, но по сравнению с болью двойных определений они того стоят.
Другой вариант, если вам не нужна независимость от компилятора / платформы, вы можете поискать что-нибудь #pragma once.
Спасибо - я использую много разных модулей / пространств имен, так что это имеет смысл. Я потеряю подчеркивание в конце. :)
Я также всегда использовал что-то вроде:
#ifndef FOO_HPP
#define FOO_HPP 1
...
#endif
Как уже упоминалось большинством людей, не добавляйте к символам двойные подчеркивания, поскольку они зарезервированы стандартом C++ для внутреннего использования реализацией.
Возможно, вы захотите взглянуть на отличную книгу Джона Лакоса «Крупномасштабный программный дизайн на C++» (Ссылка на Amazon - дезинфицировано для нацистов, использующих скрипт kiddy link) для некоторых соображений относительно включения заголовков.
HTH
ваше здоровье,
Роб
Я обычно использую:
#ifndef FILE_DATE_H_
(замените _H_ соответствующим расширением, например _HPP_ и т. д.). Штамп даты предназначен для предотвращения столкновений с другими заголовками с таким же именем в других направлениях / библиотеках.
итак, в итоге это выглядит так:
#ifndef SOMEFILE_20082411_H_
Когда мне платят за мое время, а стандарта компании еще нет, я использую:
#ifndef path_to_file_h
#define path_to_file_h
Причина использования строчных букв в том, что легче копировать и вставлять имена файлов и заменять косые черты символами подчеркивания. Причина использования #ifndef заключается в том, что он хорошо сочетается с #define, что позволяет легко увидеть, что символы совпадают. Однако мне нравится идея GUID, так что я могу попробовать.
Когда мне не платят за мое время и я не выпускаю свой код на волю, я просто использую #pragma once. В отличие от большинства других проблем с переносимостью, так же легко добавить защиту включения позже, как и сейчас, и это может сделать кто-то, кто ничего не знает о кодовой базе (например, я через год или какой-то невинный программист, которому я отправляю свой код) , поэтому применяется ЯГНИ.
я использую
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>
или же
<FILENAME_IN_ALL_CAPS>_INCLUDED_<YYYYMMDD>
Синхронизация с иерархией папок слишком раздражает (друг рефакторинга), GUID слишком раздражают, суффикс даты - достаточно хорошо. Если бы мне пришлось в один день использовать файлы с одинаковыми именами, я бы
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>a
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>b
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>...
Я бы выбрал путь к файлу + суффикс Boost _INCLUDED плюс широко поддерживаемый в настоящее время #pragma once
Во многих редакторах (для меня это превосходно) вы также можете определить для этого некоторые макросы / фрагменты.
Вот тот, который сделает это за вас:
<snippet>
<content><![CDATA[
#ifndef ${1:${TM_FILEPATH/(.*/(include|src))*([^a-zA-Z0-9_]+)*([a-zA-Z0-9_]+)([.])*([a-zA-Z0-9_]+)*/\U$4_$6/ig}_INCLUDED}
#define $1
#pragma once
$0
#endif // $1
]]></content>
<tabTrigger>incguard</tabTrigger>
<description>include guard</description>
</snippet>
так yourproject/include/yourlib/yourfile.hpp
становится YOURLIB_YOURFILE_HPP_INCLUDED
Дополнительный инструмент проверки стиля внешнего исходного кода может легко отследить согласованность ваших охранников таким образом.
Как я узнал, двойные подчеркивания зарезервированы не только в начале