Могу ли / должен ли я печатать все, что захочу после #ifndef?
Пример:
#ifndef HEADER_h
#define HEADER_h
#endif
Вместо HEADER_h
Могу ли я сделать следующее?
#ifndef HEADER
или же
#ifndef LIBRARY
или же
#ifndef SOMETHING
или же
#ifndef ANOTHERTHING
и т.п.
4 ответа
Да, вы можете назвать включаемый символ защиты как угодно, но имейте в виду, что они должны быть уникальными для разных заголовков. Вы определенно не хотите заголовок
// first.h
#ifndef NON_UNIQUE_H
#define NON_UNIQUE_H
void foo();
#endif
и еще один
// second.h
#ifndef NON_UNIQUE_H
#define NON_UNIQUE_H
void bar();
#endif
Когда вы включаете оба в одну единицу перевода, один "победит", и его объявления будут видны, например,
// main.cpp
#include "first.h" // now, NON_UNIQUE_H is defined
#include "second.h" // NON_UNIQUE_H already there, doesn't do anything
int main(int, char**)
{
bar(); // error, won't compile, bar() isn't declared
}
Помимо необходимости обходить такие сценарии, лучше придерживаться некоторых соглашений в течение всего проекта. Один из классических способов сделать это - преобразовать базовое имя файла заголовка в верхний регистр и добавить _H
, Если у вас есть заголовочные файлы с одинаковым базовым именем в разных каталогах, вы можете включить имя каталога, например SUBDIR_FOO_H
а также OTHERSUBDIR_FOO_H
, Но это зависит от вас.
Защита заголовка - это просто соглашение, "хитрость", использующая условия препроцессора. При использовании защиты заголовка вы создаете макрос с именем и проверяете, был ли этот макрос уже определен.
В этом макросе нет ничего волшебного, что связывает его с именем заголовка, и поэтому вы можете называть его как хотите (в пределах разумного).
Это не значит, что вы должны написать #ifndef URGLEBURGLE
, хоть. Вы хотите, чтобы имя было полезным и уникальным, иначе нет особого смысла.
Типично что-то вроде #ifndef [PROJECTNAME]_[FILENAME]_INCLUDED
хорошая идея
Вы можете использовать конструкцию как
#if !defined(HEADER) || !defined(LIBRARY)
На ваш вопрос вы используете
#ifndef HEADER_h
#define HEADER_h
#endif
Это то же самое, что и "#pragma Once". Да, вы можете использовать разные имена определений. В вашем случае LIBRARY, SOMETHING, HEADER_h - определяет, что вы можете установить в коде (#define MY_VAR_NAME) или с помощью параметров компилятора (флаг -DMY_VAR_NAME).
Ваш пример - так называемая защита заголовка, которая позволяет нам гарантировать, что содержимое заголовка включено только один раз. Однако это не единственное использование #ifndef
.Ты можешь использовать #ifndef
для условной компиляции как в
#ifndef NO_DEBUG
do_some_debug_stuff();
#endif
Так что это не только для охранников заголовков, но в целом вы должны тщательно выбирать имя символов, которые вы вводите, чтобы они не сталкивались с символами, определенными в другом месте. Просто защита заголовка настолько распространена, что существуют определенные соглашения (например, использование FOLDER_FILENAME_H
обычно достаточно для обеспечения уникальности). И вам нужно знать, что определенные имена зарезервированы (например, начиная с двух символов подчеркивания или подчеркивания, за которыми следует заглавная буква).