![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
JackYF |
|
||||||||||||||||||||||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 6 Всего: 162 |
Проблема множественного включения заголовочных файлов(headers) Пример: Пускай программа состоит из трёх файлов - main.cpp, a.h, b.h. a.h:
b.h:
main.cpp:
В заголовочном файле a.h описывается структура point и объявляется функция func_a. В заголовочном файле b.h включается заголовочный файл a.h и объявляется функция func_b. В основном файле программы main.cpp подключаются заголовочные файлы a.h и b.h, в функции main() поочерёдно вызываются функции func_a, func_b, затем программа завершается. Проблема: Программа не компилируется. Компилятор выдаст ошибку, например так:
Почему так происходит? Директива компилятора #include говорит компилятору о том, что содержимое указанного файла нужно вставить в данное место. Описание структуры point, итого, вставится в main.cpp два раза: 1-й раз - явно - при включении файла a.h, второй раз - неявно - при включении файла b.h, так как файл b.h тоже включает в себя содержимое файла a.h. Код главного модуля сначала преобразуется в такое:
После чего снова обрабатывается #include и получается:
В этом, итоговом, коде присутствуют два определения struct point. Это и служит причиной выдачи ошибки компилятором. Решение: Использовать условные директивы компилятора #ifndef...#define...#endif. Их также называют "стражами включения". Код всех заголовочных файлов нужно обрамлять:
Идентификатором файла может быть любое правильной имя переменной в С/С++. Однако, принято давать этим иденфикаторам имена, состоящие из больших букв латинского алфавита и подчёркиваний, логические связанные с именем файла. К примеру, для файла abcd.h можно взять идентификаторы ABCD_H, FILE_ABCD_H, ABCD_H_INCLUDED Важно: идентификаторы заголовочных файлов в пределах одной программы(одного проекта) должны быть разными, иначе Вы получите обратный результат(не множественное включения, а отсутствие включения). Исправленный заголовочный файл a.h:
Работа этих директив в данном случае заключается в том, что в первой строчке проверяется, не определено ли A_H_INCLUDED. Если определно, значит, содержимое данного файла уже было включено, и компилятору не надо обрабатывать содержимое файла повторно. Если же нет, то определяем A_H_INCLUDED и обрабатываем дальше заголовочный файл. В этом случае, код модуля с учётом произведённых #include имеет вид:
Итого получается следующее:
Это и есть желаемый нами код. Данное решение работает на всех известных компиляторах С/С++. Замечания: 1. В данном примере файл b.h тоже желательно должен быть обрамлён. 2. Не начинайте имя идентификатора с подчёркивания, это крайне не рекомендуется стандартом С++. Другие решения. Некоторые компиляторы С/С++ предоставляют ещё одно решение проблемы. Для этого необходимо включить в начало каждого заголовочного файла директиву
Данная директива имеет тот же эффект, что и вышеприведенное решение, но для её применения потребуется компилятор, поддерживающий это расширение. В число таких компиляторов входят: компилятор из MS Visual Studio (MSVC), компилятор g++ из GCC. Назад к FAQ Это сообщение отредактировал(а) bsa - 26.7.2011, 11:02 |
||||||||||||||||||||||
|
|||||||||||||||||||||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |