Подтвердить что ты не робот

Найден один или несколько многократно определенных символов

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 в заголовке, поэтому не должно встречаться несколько определений

4b9b3361

Ответ 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