# включить формат защиты заголовка?

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

#ifndef __FOO_HPP__
...

#ifndef INCLUDED_FOO_HPP
...

#ifndef SOME_OTHER_FORMAT

Мне нравится идея #define в верхнем регистре, но я не могу остановиться на формате для этих охранников.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
20
0
10 197
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Я всегда использую INCLUDED_FOO_HPP

Я бы не стал использовать двойное подчеркивание, потому что начало вещей с двойным подчеркиванием зарезервировано.

я использую

 #if !defined(FOO_HPP_INCLUDED)

Я предпочитаю современный синтаксис defined, потому что он позволяет || && операторы, даже если они здесь не используются.

Также

 #ifndef __FOO_HPP__

технически незаконно, так как начальные подчеркивания зарезервированы.

Не уверен, что за это проголосовали против. В этом нет ничего плохого, даже если бы я всегда использовал #ifndef вместо! Defined (), потому что нет необходимости использовать || или && в этом контексте.

Jonathan Leffler 24.11.2008 22:28

Я всегда использую

#ifndef FOOBAR_CPP

Если вы используете Visual Studio или компилятор Microsoft, используйте метод прагмы

#pragma once

Наверное, потому, что это непереносимо. Используйте прагму, но также поставьте защиту включения, на тот случай, если вам когда-нибудь понадобится другой компилятор.

KeithB 24.11.2008 21:44

потому что такой код заставит вас немедленно провалить собеседование со мной.

shoosh 24.11.2008 21:44

проверьте это: learningcppisfun.blogspot.com/2008/02/…

DanJ 24.11.2008 21:45

Даже если вы используете Visual Studio, вам все равно следует по возможности придерживаться стандарта.

jalf 24.11.2008 21:45

@KeithB, вопрос по переносимости не задавал.

JaredPar 24.11.2008 21:57

@Shy, если вы подводите людей к правильным ответам с правильной квалификацией, вам, вероятно, не следует ни с кем брать интервью.

JaredPar 24.11.2008 21:58

Этот ответ не получит от меня одобрения без дополнительных оговорок и оговорок в тексте. Я не уверен в голосовании против; это заманчиво, но не обязательно.

Jonathan Leffler 24.11.2008 22:25

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

KeithB 24.11.2008 23:17

Также поддерживается GCC с 3.4, это не только Microsoft. Конечно, речь идет о предпочтении портативных кодовых стоек.

Steve Jessop 25.11.2008 05:12

Обратите внимание, что Microsoft в своих собственных заголовках для VisualC++, которым нужна нулевая переносимость, использует оба стиля защиты.

James Curran 25.11.2008 15:34

Чтобы действительно избежать конфликтов имен, я использую GUID:

#ifndef GUARD_8D419A5B_4AC2_4C34_B16E_2E5199F262ED

Это имеет странный смысл :-)

Leonardo Herrera 24.11.2008 22:57

Также можно использовать дату и время - если вы не хотите создавать идентификаторы GUID.

Jack 25.11.2008 05:22

Это работает, но может сбить с толку, если вам нужно проверить включение заголовка в какой-либо файл cpp.

efotinis 25.11.2008 12:08

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

new123456 12.07.2011 02:35
Чтобы по-настоящему избежать коллизии имен с идентификаторами GUID, запретить копирование кода;) ... честно говоря: может быть сложнее проверить, имеет ли каждый уникальный заголовок в данной базе кода свой собственный уникальный защитный элемент с использованием идентификаторов GUID по сравнению с использованием идентификаторов, удобочитаемых человеком. Может быть, для каждой фиксации может быть запущен перехватчик.
Wolf 21.11.2017 13:23

Я предпочитаю такой формат:

#ifndef FOO_HPP
#define FOO_HPP

/* ... */

#endif // FOO_HPP
  • Простое #ifndef вместо #if! defined (...), потому что редко имеет смысл использовать сложное условие для защиты заголовка.
  • Часть _HPP для обозначения идентификатора в качестве защиты заголовка.
  • Нет начальных подчеркиваний, потому что такие идентификаторы (начиная с 2 подчеркиваний или с 1 подчеркивания и заглавной буквы) зарезервированы для реализации.
  • Базовая часть - это просто имя файла, FOO. Однако для кода библиотеки, который будет использоваться повторно, рекомендуется добавить еще одну часть в начале. Обычно это содержащее пространство имен или имя «модуля», например 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.

activout.se 24.11.2008 22:10
Ответ принят как подходящий

Я всегда включал пространство имен или относительный путь в защиту включения, потому что только имя заголовка оказалось опасным.

Например, у вас есть большой проект с двумя файлами где-то в вашем коде.

/myproject/module1/misc.h
/myproject/module2/misc.h

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

Итак, я согласился с

MYPROJECT_MODULE1_MISC_H_
MYPROJECT_MODULE2_MISC_H_

Эти имена довольно длинные, но по сравнению с болью двойных определений они того стоят.

Другой вариант, если вам не нужна независимость от компилятора / платформы, вы можете поискать что-нибудь #pragma once.

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

Rob 25.11.2008 00:05

Я также всегда использовал что-то вроде:

#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

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

Другие вопросы по теме