Проверка, объявлен ли уже #include - PullRequest
10 голосов
/ 07 августа 2011

Я пытаюсь проверить, было ли объявлено #include <file.h> с помощью макроса C ++.

Пример

В file.h я делаю:

#ifndef FILE.H
#define FILE.H
class A
{
  //do routines 
};
#endif

Во втором файле с именем second.h я хочу проверить, было ли уже включено file.h.

Типичный псевдо-код:

#ifndef "file.h"
#include "file.h"
#endif

#ifndef SECOND.H
#define SECOND.H
class second
{
  //do routine
};
#endif

Я попробовал несколько директив #ifndefно не радостьКто-нибудь знает, как этого добиться?

Ответы [ 5 ]

10 голосов
/ 07 августа 2011

Все остальные рассмотрели правильное включение макросов include guard.

File.h

#ifndef   FILE_H
#define   FILE_H
// Code here
#endif

Но все остальные пропустили вторую часть вашего вопроса о правильном использовании:

Это пример неправильного использования:

#ifndef  FILE_H  
#include "file.h"
#endif

#ifndef SECOND_H
#define SECOND_H
class second
{
  //do routine
};
#endif

Это неверно (хотя оно может быть слишком сильным).

Защитные ограждения в каждом файле должны окружать весь их контент.Итак, во втором файле #include "file.h" должен быть внутри включенных защит.

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

#ifndef SECOND_H
#define SECOND_H

#include "file.h"

class second
{
  //do routine
};
#endif

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

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

#ifndef    WEBSITE1_NAMESPACE1_NAMESPACE2_FILENAME_H
#define    WEBSITE1_NAMESPACE1_NAMESPACE2_FILENAME_H

#endif

Другой альтернативой (особенно если вы работаете в Windows) является генерация GUID.Просто создайте новый файл для каждого файла.

Конечный момент: включайте другие файлы из заголовочных файлов только в том случае, если их содержание абсолютно необходимо.Вам нужно только включить «file.h», если этот файл имеет определение типа, от которого зависит секунда класса.Если ваш класс использует этот класс только в качестве указателя или ссылки, то предпочтительнее использовать предварительное объявление, а не заголовочный файл.

Сценарии, в которых вы должны #include:

  • second - дочерний элемент first.
  • second имеет первый (-ые) элемент (-ы) objects
  • second имеет метод (ы), которые принимают first objects в качестве параметров
  • Second имеет метод (ы), которые возвращают первый objects в результате

Обратите внимание, что я использую термин "объекты".Если они являются ссылками или указателями, то это не считается.В этих случаях вы можете использовать предварительное объявление для решения проблемы.

7 голосов
/ 07 августа 2011

в file.h:

#ifndef FILE_H
#define FILE_H
...
...
...
#endif

Затем проверьте, включен ли file.h с:

#ifdef FILE_H
2 голосов
/ 07 августа 2011

Простая причина для строки #ifndef FILE_H в заголовке состоит в том, чтобы сделать ее такой, чтобы при втором и последующих включениях файл не использовался.Эти # строки, взятые вместе, известны как «include guard».

Таким образом, простое выполнение #include "file.h" уже сделает то, что вы пытаетесь сделать во втором файле.(Препроцессор, вероятно, откроет и прочитает файл перед тем, как выбросить его содержимое, но разумно предположить, что он находится в кеше, и, следовательно, в общем случае повышение производительности компилятора не ожидается.

Если выпожаловаться на то, что файл не включен, вы можете просто включить его самостоятельно. Возможно, вы хотите запретить включение файла при включении другого файла, так что они являются или-или; или строгий порядок включений (возможно, является признаком проблемы проектирования)). Или используйте альтернативный код, когда что-то было (не) включено.

В таких случаях #ifdef X или #ifndef X, где X соответствует тому, что используется во включаемом ограждении, будет работать.

2 голосов
/ 07 августа 2011

В файле file.h

#ifndef FILE_H_
#define FILE_H_
#else
#error file.h has been included previously
#endif

Но это приведет к тому, что ваша программа не будет компилироваться, если вы включите file.h более одного раза.То, что вы, вероятно, хотите, это

#ifndef FILE_H_
#define FILE_H_

// contents of file.h go here

#endif

Это предотвратит ошибки / предупреждения компиляции из-за многократного включения.

1 голос
/ 07 августа 2011

Типичный способ сделать что-то вроде этого:

#ifndef _FILE_H_
#define _FILE_H_

// some code

#endif

Это предотвратит многократное включение одного и того же заголовка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...