Именование включает охранников

Как С++ включают в себя защитные устройства, которые обычно называются? Я очень часто вижу это:

#ifndef FOO_H
#define FOO_H

// ...

#endif

Однако я не считаю это очень интуитивным. Не видя имени файла, трудно сказать, что такое FOO_H и для чего оно относится.

Что считается лучшей практикой?

Ответ 1

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

Итак test.h становится TEST_H.

Реальные примеры этого включают Qt Creator, который следует этому соглашению при автогенерации файлов заголовков классов.

Ответ 2

Я лично следую рекомендациям Boost. Это, возможно, одна из самых больших библиотек С++ хорошего качества, и у них нет проблем.

Это выглядит так:

<project>_<path_part1>_..._<path_partN>_<file>_<extension>_INCLUDED

// include/pet/project/file.hpp
#ifndef PET_PROJECT_FILE_HPP_INCLUDED

который:

  • legal (обратите внимание, что начало с помощью _[A-Z] или содержащее __ не является)
  • легко сгенерируется
  • гарантированно будет уникальным (в качестве защитника) в рамках проекта (иначе у вас есть два файла в одном месте)
  • гарантированно не будет использоваться ни для чего другого (если вы закончите другой макрос с помощью INCLUDED, вы портитесь для боя)

Я читал о GUID, но они выглядят странно.

И, очевидно, я предпочел бы, чтобы все компиляторы реализовали #pragma once (или лучше, #pragma multiple и "once" - поведение по умолчанию...)

Ответ 3

Взято непосредственно из руководства по стилю google:

Все файлы заголовков должны содержать #define guard для предотвращения множественного включения. Формат имени символа должен быть <PROJECT> _ <PATH> _ <FILE> _H_. Чтобы гарантировать уникальность, они должны основываться на полном пути в исходном дереве проекта. Например, файл foo/src/bar/baz.h в проекте foo должен иметь следующую защиту:

 #ifndef FOO_BAR_BAZ_H_
 #define FOO_BAR_BAZ_H_
 ...
 #endif  // FOO_BAR_BAZ_H_

Я использую этот стиль в своих проектах.

Ответ 4

Посмотрите на код, который # включает ваш заголовок.

Если это что-то вроде:

#include "mylib/myheader.h"

mylib/myheader.h уже является уникальным именем. Просто капитализируйте и замените/и. с _

#define MYLIB_MYHEADER_H

Если у вас есть два заголовка на вашем пути include с тем же именем относительно пути include, у вас уже есть столкновение на этом уровне.

Ответ 5

Замените FOO_H на FOO_H_INCLUDED и понятнее.

Ответ 6

Как упоминалось ранее, очень распространенное соглашение заключается в использовании прописной версии имени, а точка заменяется на символ подчеркивания: foo.h → FOO_H

Однако это может привести к конфликтам имен с простыми и/или общими именами. По этой причине автогенерированный заголовок, такой как stdafx.h в непустых проектах Visual C С++, добавляет некоторую случайную строку, например:

#ifndef FOO_H__NsknZfLkajnTFBpHIhKS
#define FOO_H__NsknZfLkajnTFBpHIhKS
#endif

http://www.random.org/strings/ - полезный случайный генератор для этого.

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

#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS

namespace somecomponent
{
  ...
}

#endif

Ответ 7

Обычно я использую что-то вроде FOO_H_INCLUDED_. Несколько (Microsoft) заголовков имеют то, что очень похоже на строковое представление GUID, но мне никогда не нужно было ничего такого, что было бы сложнее.

Ответ 8

Обычно люди делают это по имени файла, поэтому каждый код файла только компилируется и добавляется один раз. Вы могли бы сделать FOO_H всем, что хотите, но почти все, что я когда-либо кодировал или видел, использовал имя файла. Просто убедитесь, что он уникален, потому что вы не хотите, чтобы ваш FOO_H противоречил кому-то еще FOO_H.

Ответ 9

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