Заголовок охранников в C ++ и C - PullRequest
30 голосов
/ 22 января 2011

В LearnCpp.com | 1.10 - Первый взгляд на препроцессор . Под Заголовком есть следующие фрагменты кода:

add.h:

#include "mymath.h"
int add(int x, int y);

subtract.h:

#include "mymath.h"
int subtract(int x, int y);

main.cpp:

#include "add.h"
#include "subtract.h"

При реализации защиты заголовка упоминается следующее:

#ifndef ADD_H
#define ADD_H

// your declarations here

#endif
  • Что здесь может быть декларация? И, если int main() придет после #endif?
  • Является ли добавление _H соглашением или обязательным условием?

Спасибо.

Ответы [ 5 ]

54 голосов
/ 22 января 2011

FILENAME_H - это соглашение. Если вы действительно хотите, вы можете использовать #ifndef FLUFFY_KITTENS в качестве защиты заголовка (при условии, что она не была определена где-либо еще), но это будет хитрая ошибка, если вы определите ее где-то еще, скажем, как количество котят для чего-то или другого.

В заголовочном файле add.h объявления находятся буквально между #ifndef и #endif.

#ifndef ADD_H
#define ADD_H

#include "mymath.h"
int add(int x, int y);

#endif

Наконец, int main() не должно быть в заголовочном файле. Он всегда должен быть в файле .cpp.

Чтобы очистить это:

#ifndef ADD_H в основном означает «если ADD_H не было #defined в файле или во включенном файле, то скомпилировать код между директивами #ifndef и #endif». Поэтому, если вы попытаетесь #include "add.h" более одного раза в файле .cpp, компилятор увидит, что ADD_H уже было #defined, и проигнорирует код между #ifndef и #endif. Защита заголовка только предотвращает включение файла заголовка несколько раз в один и тот же файл .cpp. Защита заголовка не запрещает другим файлам .cpp включать файл заголовка. Но все .cpp файлы могут включать защищенный заголовочный файл только один раз .

17 голосов
/ 22 января 2011
  • Результатом предварительной обработки одного файла реализации (".cpp") является единица перевода (TU).

  • Заголовки могут включать другие заголовки, поэтомузаголовок может быть косвенно включен несколько раз в один и тот же TU.(Ваш mymath.h является примером этого.)

  • Определения могут встречаться не более одного раза за TU.(Некоторые определения также не должны быть в нескольких TU; этот случай немного отличается и здесь не обсуждается.)

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

  • Включите охрану, "обернув" содержимое заголовка таким образом, что второе и последующее включение не будут выполнены.Директивы # ifndef / # define должны быть первыми двумя строками файла, а #endif должен быть последним.

  • Включающие охранники используются только в заголовках.Не определяйте свою основную функцию в заголовке: поместите ее в файл реализации.

Если у вас есть заголовок, который определит тип и объявит функцию, но также нуждается в самом заголовке:

#include "other_header.h"

struct Example {};

void f();

"Обертывание" с включенными охранниками дает полное содержимое файла:

#ifndef UNIQUE_NAME_HERE
#define UNIQUE_NAME_HERE

#include "other_header.h"

struct Example {};

void f();

#endif

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

3 голосов
/ 22 января 2011

Все, что делают охранники заголовков, это разрешает включать заголовки только один раз.(Если они включены несколько раз, они игнорируются.)

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

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

1 голос
/ 22 января 2011

Я объявляю объявление в заголовочном файле и определениях или int main() входит в source.cpp файл.

_H просто для того, чтобы указать, что кто-то собирается включить заголовочные файлы с использованием include guard.

Если вы используете MSVC ++, вы также можете использовать #pragma once

1 голос
/ 22 января 2011

Нет, int main () идет в .cpp.Декларации - это другой материал, который вы собирались поместить в заголовок._H - это соглашение, вы можете увидеть различные соглашения о защите заголовка.

...