Именование включает охрану - PullRequest
20 голосов
/ 01 февраля 2011

Как в C ++ обычно включаются охранники? Я часто вижу это:

#ifndef FOO_H
#define FOO_H

// ...

#endif

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

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

Ответы [ 9 ]

21 голосов
/ 02 февраля 2011

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

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

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

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

, что:

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

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

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

17 голосов
/ 01 февраля 2011

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

То есть test.h становится TEST_H.

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

12 голосов
/ 01 февраля 2011

Взят прямо из руководства по стилю Google :

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

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

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

5 голосов
/ 02 февраля 2011

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

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

#include "mylib/myheader.h"

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

#define MYLIB_MYHEADER_H

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

3 голосов
/ 01 февраля 2011

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

2 голосов
/ 02 февраля 2011

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

Однако это может привести к конфликтам именс простыми и / или общими именами.По этой причине автоматически сгенерированный заголовок, такой как stdafx.h, в непустых проектах Visual C 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
1 голос
/ 01 февраля 2011

Обычно я смотрю, который частот факт, что это загадочно.

1 голос
/ 01 февраля 2011

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

1 голос
/ 01 февраля 2011

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

...