Как избежать двойного включения: директива препроцессора или make-файлы

Я работаю над переходом от франкенштейновских и однофайловых программ с тысячами строк к хорошо структурированным и организованным многофайловым программам. Прямо сейчас то, что кажется естественным (наивно), это сделать любовный треугольник включений заголовков для трех моих файлов:
файл_1 включает файл_2, файл_4
файл_2 включает файл_3, файл_4
файл_3 включает файл_1 .... и т. д.
Эти файлы имеют переменные, методы, структуры и т. Д., Которые мне нужны между другими файлами.

И конечно я получаю двойные ошибки включения.

Мой вопрос: должен ли я избежать этих проблем, используя директивы препроцессора в заголовках (например, включая структуры, методы и т. Д. Целиком в заголовке), или я должен компилировать с использованием make-файла (который, как я слышал, также может быть использован для решения этой проблемы - - но я никогда не делал один)?

4 ответа

Решение

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

  • Структуры
  • переменная общего доступа как extern (и определить ее в одном из файлов.c)
  • объявление метода (и определение методов в одном из файлов.c)

защитить их #IFNDEF а также #ENDIF, затем включите заголовочный файл в различные файлы.c...

Вы всегда должны использовать include guard, чтобы при необходимости вы могли включать ваши общие заголовочные файлы. Это действительно не зависит от Makefile или любого другого инструмента сборки, который вы выберете.

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

Примером включения защиты для inv_tree.h будет

#ifndef INV_TREE_H
#define INV_TREE_H
...
#endif

Окружая содержимое "inv_tree.h" с помощью сторожа, он проверяет, была ли определена погода INV_TREE_H, прежде чем включать "inv_tree.h". Если он не был определен, он определяет его и включает в себя "inv_tree.h", в противном случае он не включает его

заголовочные файлы

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

Если вы используете только ссылку или указатель на класс, объявите его только вперед (не включайте файл heder).

Таким образом, вы можете прервать включение циклического заголовка.

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

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