Могу ли / должен ли я печатать все, что захочу после #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 обычно достаточно для обеспечения уникальности). И вам нужно знать, что определенные имена зарезервированы (например, начиная с двух символов подчеркивания или подчеркивания, за которыми следует заглавная буква).

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