Найден один или несколько многократно определенных символов
DebugUtil.h
#ifndef DEBUG_UTIL_H #define DEBUG_UTIL_H #include int DebugMessage(const char* message) { const int MAX_CHARS = 1023; static char s_buffer[MAX_CHARS+1]; return 0; } #endif
Когда я пытаюсь запустить это, я получаю эту ошибку:
Terrain.obj: ошибка LNK2005: «int __cdecl DebugMessage (char const *)» (? DebugMessage @@ YAHPBD @ Z), уже определенный в Loodus.obj
- C ++ 11: Исправить инициализацию std :: array?
- Как отсортировать вектор пар на основе второго элемента пары?
- Как уменьшить размер исполняемого файла, созданного компилятором MinGW g ++?
- Инструменты для получения графического графика вызова функции кода
- C ++ 11 - static_assert в функции constexpr?
Renderer.obj: ошибка LNK2005: «int __cdecl DebugMessage (char const *)» (? DebugMessage @@ YAHPBD @ Z), уже определенный в Loodus.obj
test.obj: ошибка LNK2005: «int __cdecl DebugMessage (char const *)» (? DebugMessage @@ YAHPBD @ Z), уже определенный в Loodus.obj
C: \ Users \ Tiago \ Desktop \ Loodus Engine \ Debug \ Loodus Engine.exe: фатальная ошибка LNK1169: найден один или несколько множимых символов
Но почему это происходит? У меня есть #ifndef #define и #endif в заголовке, поэтому несколько определений не должно происходить
- Как перечислить все поля в файле PDF в ITextSharp
- неверное преобразование из `void * 'в` char *' при использовании malloc?
- cin и getline пропускают ввод
- Как вы это называете, когда один интерфейс «наследует» от другого?
- Удалить элемент регулярного массива
- Отображение типа CLR типа EDM неоднозначно с EF 6 и 5?
- Что делают компиляторы с разветвлением во время компиляции?
- Почему я не могу сделать foreach (var Item в DataTable.Rows)?
Поместите определение (тело) в файл cpp и оставьте только объявление в файле ah. Включите защитные устройства, работающие только в пределах одной единицы перевода (как исходный файл), а не во всей вашей программе.
Правило одного определения стандарта C ++ утверждает, что должно отображаться ровно одно определение каждой не-встроенной функции, которая используется в программе. Таким образом, еще одна альтернатива – сделать вашу функцию встроенной.
Сделайте функцию inline или объявите функцию в файле заголовка и определите ее в файле cpp.
inline int DebugMessage(const char* message) { const int MAX_CHARS = 1023; static char s_buffer[MAX_CHARS+1]; return 0; }
РЕДАКТИРОВАТЬ:
Как отмечает Tomalak Geret’kal, лучше использовать мои последние предложения, чем мои прежние, и перенести объявление функции в файл cpp.
(Предполагая, что опубликованный код является заголовком, включенным в несколько файлов .cpp)
Защитники заголовков не защищают вас от множественных определений ссылок. Независимо от того, что вы обеспечили, чтобы заголовок появлялся только один раз для единицы перевода, если у вас более одного модуля перевода, это все еще несколько определений.
Напишите определения в исходных файлах и только объявления в заголовках.
Единственными исключениями являются inline
функции, функции, определенные в определении class
(хотя это не рекомендуется!) И шаблоны функций.
Эта функция включена в каждую единицу перевода, и в результате вы получаете несколько определений – каждый .obj-файл содержит свою собственную копию. Когда пришло время связать их все вместе, компоновщик по праву показывает ошибку выше.
Вы можете сделать несколько вещей:
- Переместите определение в файл .cpp и сохраните только объявление в заголовке.
- Используйте анонимное пространство имен вокруг функции в вашем файле заголовка (но понимайте, что это взломать – у вас все еще будет несколько определений, просто нет столкновения имен).
- Отметьте его как встроенный (хотя он может не всегда работать – только если компилятор действительно хочет его встроить). Это также взломать по той же причине, что и выше.
Переместите определение в файл .cpp.
Объявите свои функции в файлах на C ++. Поскольку вы определили свою функцию в файле заголовка, и этот файл заголовка включен из нескольких исходных файлов, он определяется для каждого исходного файла, который включает его. Вот почему это сообщается как определено в нескольких местах.
Кроме того, вы можете сделать его встроенным, чтобы код вставлялся везде, где он используется, а не каждый раз определялся как отдельная функция.
Похоже, что вы включаете DebugUtil.h в несколько единиц перевода, а затем соединяете эти объекты вместе. Тем не менее, DebugUtil.h предоставляет определение функции DebugMessage, так что определение существует во всех единицах перевода, которые включали заголовок. В результате, когда вы связываете объекты, компоновщик справедливо жалуется, что символ многократно определен.
Измените DebugUtil.h так, чтобы он декларировал DebugMessage через прототип, но не дал определения и поместил определение DebugMessage в файл .c, который вы будете компилировать и связать с другими объектами.
Это предотвращает только множественные включения в одном исходном файле; несколько исходных файлов #include
ing все равно будут генерировать несколько определений DebugMessage()
. В общем, вы должны либо не размещать функции в файлах заголовков вообще, либо сделать их static
(и обычно inline
, так как в противном случае обычно не имеет смысла иметь несколько static
определений одной и той же функции).
100% Вы правильно включили гвардейцев, но все еще получаете ошибку переопределения?
Для Visual Studio: я был очень расстроен, потому что я был правильно включен охранниками, но только для выяснения проблемы была визуальная студия. Если вы добавили файл в свой проект, компилятор добавит файл дважды, даже если у вас есть защита от файла реализации и файла заголовка.
Если вы не используете эксклюзивную визуальную студию и говорите … иногда используйте code :: blocks, вы можете захотеть только # включить файл, если обнаружите отсутствие среды визуальной студии.
DebugUtil.h : ---------------------- #ifndef _WIN32 #include "DebugUtil.c" #endif ----------------------
Если у вас все в порядке, включая stdio.h, вы можете быть немного менее хакерскими:
DebugUtil.h : ---------------------- #include #ifdef _MSC_VER #include "DebugUtil.c" #endif ----------------------
Ссылка: предопределенные macros, Visual Studio: https://msdn.microsoft.com/en-us/library/b0084kay.aspx