Найден один или несколько многократно определенных символов
DebugUtil.h
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H
#include <windows.h>
int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
#endif
Когда я пытаюсь запустить это, я получаю эту ошибку:
Terrain.obj: ошибка LNK2005: "int msgstr" (? определенный в Loodus.obj
Renderer.obj: ошибка LNK2005: "int msgstr" (? определенный в Loodus.obj
test.obj: ошибка LNK2005: "int __cdecl DebugMessage (char const *)" (? DebugMessage @@YAHPBD @Z) уже определенный в Loodus.obj
C:\Users\Тьяго\Desktop\Loodus Engine\Debug\Loodus Engine.exe: смертельный ошибка LNK1169: один или несколько умножений Определенные символы найдены
Но почему это происходит? У меня есть #ifndef #define и #endif в заголовке, поэтому не должно встречаться несколько определений
Ответы
Ответ 1
Поместите определение (тело) в файл cpp и оставьте только объявление в файле h. Включить охранники работают только в пределах одной единицы перевода (как исходный файл), а не во всей вашей программе.
В одном правиле определения стандарта С++ указано, что должно отображаться ровно одно определение каждой не-встроенной функции, которая используется в программе. Таким образом, другой альтернативой было бы сделать вашу функцию встроенной.
Ответ 2
Сделайте функцию inline или объявите функцию в файле заголовка и определите ее в файле cpp.
inline int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
EDIT:
Как отмечает Tomalak Geret'kal, лучше использовать мои последние предложения, чем мои прежние, и переместить объявление функции в файл cpp.
Ответ 3
(Предполагая, что опубликованный код является заголовком, включенным в несколько файлов .cpp)
Защитники заголовков не защищают вас от множественных определений ссылок. Независимо от того, что вы гарантировали, что заголовок будет отображаться только один раз для модуля перевода, если у вас есть несколько модулей перевода, то это все еще несколько определений.
Записывать определения в исходные файлы и только объявления в заголовках.
Единственными исключениями являются функции inline
, функции, определенные в определении class
(хотя это не рекомендуется!) и шаблоны функций.
Ответ 4
Эта функция включена в каждую единицу перевода, и в результате вы получаете несколько определений - каждый .obj файл содержит свою собственную копию. Когда это время, чтобы связать их все вместе, компоновщик по праву показывает ошибку выше.
Вы можете сделать несколько вещей:
- Переместите определение в файл .cpp и сохраните только объявление в заголовке.
- Используйте анонимное пространство имен вокруг функции в вашем файле заголовка (но понимайте, что это взломать - у вас все еще будет несколько определений, просто нет столкновения имен).
- Отметьте его как встроенный (хотя он может не всегда работать - только если компилятор действительно хочет его встроить). Это также взломать по той же причине, что и выше.
Ответ 5
Переместите определение в файл .cpp.
Ответ 6
Объявите свои функции в файлах на С++. Поскольку вы определили свою функцию в файле заголовка, и этот файл заголовка включен из нескольких исходных файлов, он определяется для каждого исходного файла, который включает его. Именно поэтому он сообщил, что он определен в нескольких местах.
В качестве альтернативы вы можете сделать его встроенным, чтобы код вставлялся везде, где он использовался, а не каждый раз определялся как отдельная функция.
Ответ 7
Похоже, вы включаете DebugUtil.h в несколько единиц перевода, а затем соединяете эти объекты вместе. Тем не менее, DebugUtil.h предоставляет определение функции DebugMessage, так что определение существует во всех единицах перевода, которые включали заголовок. В результате, когда вы связываете объекты, компоновщик правильно жалуется, что символ размножен.
Измените DebugUtil.h так, чтобы он декларировал DebugMessage через прототип, но не предоставил определение и поместил определение DebugMessage в файл .c, который вы будете компилировать и связать с другими объектами.
Ответ 8
Это предотвращает только множественные включения в одном исходном файле; несколько исходных файлов #include
ing все равно будут генерировать несколько определений DebugMessage()
. В общем случае вы должны либо не размещать функции в файлах заголовков вообще, либо делать их static
(и обычно inline
, так как в противном случае обычно не имеет смысла иметь несколько определений static
для одной и той же функции).
Ответ 9
100% Некоторые ваши соблазнительные гауры верны, но все еще получают ошибку переопределения?
Для Visual Studio:
Я был очень сердитым, потому что я правильно делал свои гауры,
только для выяснения проблемы была визуальная студия. Если вы добавили файл
к вашему проекту, компилятор добавит файл дважды, даже если у вас есть
включают gaurds вокруг вашего файла реализации и файла заголовка.
Если вы не используете исключительно визуальную студию и говорите... иногда используйте код:: блоки, вы можете захотеть только # включить файл, если обнаружите отсутствие среды визуальной студии.
DebugUtil.h :
----------------------
#ifndef _WIN32
#include "DebugUtil.c"
#endif
----------------------
Если вы в порядке с включением stdio.h,
вы можете быть немного менее хакерскими:
DebugUtil.h :
----------------------
#include <stdio.h>
#ifdef _MSC_VER
#include "DebugUtil.c"
#endif
----------------------
Ссылка:
Предопределенные макросы, Visual Studio:
https://msdn.microsoft.com/en-us/library/b0084kay.aspx