Как избавиться от redefinition
JackYF |
| ||
полуавантюрист Профиль Репутация: 6 Пускай программа состоит из трёх файлов — main.cpp, a.h, b.h.
void func_a(); |
Код |
#include «a.h» |
void func_b(point* pnt);
Код |
#include «a.h» #include «b.h» |
return 0;
>
В заголовочном файле a.h описывается структура point и объявляется функция func_a.
В заголовочном файле b.h включается заголовочный файл a.h и объявляется функция func_b.
В основном файле программы main.cpp подключаются заголовочные файлы a.h и b.h, в функции main() поочерёдно вызываются функции func_a, func_b, затем программа завершается.
Проблема:
Программа не компилируется. Компилятор выдаст ошибку, например так:
Код |
a.h:1: error: redefinition of ‘struct point’ |
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
В этом, итоговом, коде присутствуют два определения struct point. Это и служит причиной выдачи ошибки компилятором.
Решение:
Использовать условные директивы компилятора #ifndef. #define. #endif.
Их также называют «стражами включения».
Код всех заголовочных файлов нужно обрамлять:
Код |
#ifndef идентификатор_файла #define идентификатор_файла |
// здесь всё, что было раньше в заголовочном файле
Идентификатором файла может быть любое правильной имя переменной в С/С++.
Однако, принято давать этим иденфикаторам имена, состоящие из больших букв латинского алфавита и подчёркиваний, логические связанные с именем файла.
К примеру, для файла abcd.h можно взять идентификаторы ABCD_H, FILE_ABCD_H, ABCD_H_INCLUDED
Важно: идентификаторы заголовочных файлов в пределах одной программы(одного проекта) должны быть разными, иначе Вы получите обратный результат(не множественное включения, а отсутствие включения).
Исправленный заголовочный файл a.h:
Код |
#ifndef A_H_INCLUDED // если этот файл ещё не включён #define A_H_INCLUDED // включить этот файл |
void func_a();
#endif
Работа этих директив в данном случае заключается в том, что в первой строчке проверяется, не определено ли A_H_INCLUDED. Если определно, значит, содержимое данного файла уже было включено, и компилятору не надо обрабатывать содержимое файла повторно. Если же нет, то определяем A_H_INCLUDED и обрабатываем дальше заголовочный файл.
В этом случае, код модуля с учётом произведённых #include имеет вид:
Код |
#ifndef A_H_INCLUDED // идентификатор ещё не определён #define A_H_INCLUDED // определяем |
#ifndef A_H_INCLUDED // а здесь идентификатор уже определён
#define A_H_INCLUDED // поэтому эта и все остальные строки до #endif удаляются
void func_b(point* pnt);
return 0;
>
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
Это и есть желаемый нами код.
Данное решение работает на всех известных компиляторах С/С++.
Замечания:
1. В данном примере файл b.h тоже желательно должен быть обрамлён.
2. Не начинайте имя идентификатора с подчёркивания, это крайне не рекомендуется стандартом С++.
Другие решения.
Некоторые компиляторы С/С++ предоставляют ещё одно решение проблемы.
Для этого необходимо включить в начало каждого заголовочного файла директиву
Данная директива имеет тот же эффект, что и вышеприведенное решение, но для её применения потребуется компилятор, поддерживающий это расширение. В число таких компиляторов входят: компилятор из MS Visual Studio (MSVC), компилятор g++ из GCC.
Это сообщение отредактировал(а) bsa — 26.7.2011, 11:02
[ Время генерации скрипта: 0.1008 ] [ Использовано запросов: 21 ] [ GZIP включён ] Источник How to prevent macro redefinitionAfter working some time on my project, this warning begins to appear: I’m sure that it’s a matter of the order of the include files to solve, because none of these files are mine. My question is if there is a generic way to prevent this or to find which files must to be reordered to avoid this message. 5 Answers 5The error message itself is telling you the incorrect order. It says that windef.h and wingdi.h are redefining symbols that were defined in glfw.h . Put glfw.h after the Windows include files. Microsoft doesn’t generally design headers to be free-standing. Most of the Windows-oriented headers require that you have first included . Except for the dependency on that Mother Of All Headers, usually there are no specific header dependencies so by including first you shouldn’t have any problem. The problem is in the file Game.cpp. Try to include windows.h before glfw.h. There is a guard in glfw.h which will prevent that warning: Unfortunately or fortunately, no. There is no such tool that automates it. You have to go read the code in those header files, figure out what is going on and take appropriate actions. The most you can do is
Only ANSI C considers macro redefinition an error. Источник Как избавиться от redefinition
void func_b(point* pnt);
return 0; |
В заголовочном файле a.h описывается структура point и объявляется функция func_a.
В заголовочном файле b.h включается заголовочный файл a.h и объявляется функция func_b.
В основном файле программы main.cpp подключаются заголовочные файлы a.h и b.h, в функции main() поочерёдно вызываются функции func_a, func_b, затем программа завершается.
Проблема:
Программа не компилируется. Компилятор выдаст ошибку, например так:
Код |
a.h:1: error: redefinition of ‘struct point’ |
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
В этом, итоговом, коде присутствуют два определения struct point. Это и служит причиной выдачи ошибки компилятором.
Решение:
Использовать условные директивы компилятора #ifndef. #define. #endif.
Их также называют «стражами включения».
Код всех заголовочных файлов нужно обрамлять:
Код |
#ifndef идентификатор_файла #define идентификатор_файла |
// здесь всё, что было раньше в заголовочном файле
Идентификатором файла может быть любое правильной имя переменной в С/С++.
Однако, принято давать этим иденфикаторам имена, состоящие из больших букв латинского алфавита и подчёркиваний, логические связанные с именем файла.
К примеру, для файла abcd.h можно взять идентификаторы ABCD_H, FILE_ABCD_H, ABCD_H_INCLUDED
Важно: идентификаторы заголовочных файлов в пределах одной программы(одного проекта) должны быть разными, иначе Вы получите обратный результат(не множественное включения, а отсутствие включения).
Исправленный заголовочный файл a.h:
Код |
#ifndef A_H_INCLUDED // если этот файл ещё не включён #define A_H_INCLUDED // включить этот файл |
void func_a();
#endif
Работа этих директив в данном случае заключается в том, что в первой строчке проверяется, не определено ли A_H_INCLUDED. Если определно, значит, содержимое данного файла уже было включено, и компилятору не надо обрабатывать содержимое файла повторно. Если же нет, то определяем A_H_INCLUDED и обрабатываем дальше заголовочный файл.
В этом случае, код модуля с учётом произведённых #include имеет вид:
Код |
#ifndef A_H_INCLUDED // идентификатор ещё не определён #define A_H_INCLUDED // определяем |
#ifndef A_H_INCLUDED // а здесь идентификатор уже определён
#define A_H_INCLUDED // поэтому эта и все остальные строки до #endif удаляются
void func_b(point* pnt);
return 0;
>
Код |
struct point < int x; int y; >; |
void func_b(point* pnt);
return 0;
>
Это и есть желаемый нами код.
Данное решение работает на всех известных компиляторах С/С++.
Замечания:
1. В данном примере файл b.h тоже желательно должен быть обрамлён.
2. Не начинайте имя идентификатора с подчёркивания, это крайне не рекомендуется стандартом С++.
Другие решения.
Некоторые компиляторы С/С++ предоставляют ещё одно решение проблемы.
Для этого необходимо включить в начало каждого заголовочного файла директиву
Данная директива имеет тот же эффект, что и вышеприведенное решение, но для её применения потребуется компилятор, поддерживающий это расширение. В число таких компиляторов входят: компилятор из MS Visual Studio (MSVC), компилятор g++ из GCC.
Это сообщение отредактировал(а) bsa — 26.7.2011, 11:02
[ Время генерации скрипта: 0.1026 ] [ Использовано запросов: 22 ] [ GZIP включён ] Источник |