ошибка LNK2005, уже определилась?
У меня есть 2 файла, A.cpp и B.cpp, в консольном приложении Win32.
Оба файла содержат только следующие 2 строки кода:
При компиляции выдает ошибку
Я не понимаю, что происходит.
Может кто-нибудь объяснить мне это?
Почему эта ошибка?
Вы нарушили одно правило определения и, следовательно, ошибку связывания.
Предлагаемые решения:
Если вам нужна переменная с одинаковым именем в двух файлах cpp, вам необходимо использовать пространство имен без имени (анонимное пространство имен), чтобы избежать ошибки.
Если вам нужно использовать одну и ту же переменную в нескольких файлах, вам нужно использовать extern .
Ах
A.cpp
B.cpp

В настройках проекта добавьте /FORCE:MULTIPLE параметры командной строки компоновщика .
Из MSDN : «Используйте / FORCE: MULTIPLE, чтобы создать выходной файл независимо от того, находит ли LINK более одного определения для символа».

wxString определяется в двух файлах .obj. Это решение позволяет мне продолжать писать модульные тесты без полного рефакторинга поддерживаемого мной кода (который требует рефакторинга, но это займет некоторое время).
Если вы хотите, чтобы оба ссылались на одну и ту же переменную, одна из них должна иметь int k; , а другая — extern int k;
В этой ситуации вы обычно помещаете определение ( int k; ) в один .cpp файл и помещаете объявление ( extern int k; ) в заголовок, который будет включен везде, где вам нужен доступ к этой переменной.
Если вы хотите, чтобы каждая из k них была отдельной переменной, которая случайно имела одно и то же имя, вы можете либо пометить их как static , например: static int k; (во всех файлах или хотя бы во всех файлах, кроме одного). В качестве альтернативы вы можете использовать анонимное пространство имен:
Опять же, во всех файлах, кроме одного.
В C компилятор обычно не так разборчив в этом вопросе. В частности, в C есть понятие «предварительное определение», поэтому, если у вас есть что-то вроде int k; двух (в одном и том же или в разных исходных файлах), каждое из них будет рассматриваться как предварительное определение, и между ними не будет конфликта. Однако это может немного сбивать с толку, потому что у вас все еще не может быть двух определений, которые оба включают инициализаторы — определение с инициализатором всегда является полным определением, а не предварительным определением. Другими словами, int k = 1; появление дважды было бы ошибкой, но int k; в одном месте и int k = 1; в другом — нет. В этом случае, int k; будет рассматриваться как предварительное определение, а int k = 1; как определение (и оба относятся к одной и той же переменной).
Ошибка средств компоновщика LNK2005
За этой ошибкой следует Неустранимая ошибка LNK1169.
Возможные причины и решения
Как правило, эта ошибка означает, что вы нарушили одно правило определения, которое допускает только одно определение любого используемого шаблона, функции, типа или объекта в данном объектном файле и только одно определение во всем исполняемом объекте для внешних видимых объектов или функций.
Ниже приведены некоторые распространенные причины этой ошибки.
Эта ошибка может возникать, когда заголовочный файл определяет переменную. Например, если включить этот файл заголовка в более чем один исходный файл в проекте, возникает ошибка:
Ниже представлены возможные решения.
Объявите переменную extern в файле заголовка: extern int global_int; , затем определите ее и при необходимости инициализируйте ее в одном и только одном исходном файле: int global_int = 17; . Теперь эта переменная является глобальной, которую можно использовать в любом исходном файле путем объявления ее extern , например, путем включения файла заголовка. Мы рекомендуем использовать это решение для переменных, которые должны быть глобальными, но хорошей практикой разработки программного обеспечения является сокращение числа глобальных переменных.
Объявите переменную static: static int static_int = 17; . Это ограничивает область определения текущим объектным файлом и позволяет нескольким файловым файлам иметь собственную копию переменной. Не рекомендуется определять статические переменные в файлах заголовков из-за возможности путаницы с глобальными переменными. Предпочитают перемещать определения статических переменных в исходные файлы, которые их используют.
Объявите переменную selectany: __declspec(selectany) int global_int = 17; . Это предписывает компоновщику выбрать одно определение для использования всеми внешними ссылками и отменить остальные. Это решение иногда полезно при объединении библиотек импорта. В противном случае мы не рекомендуем использовать его как способ избежать ошибок компоновщика.
Эта ошибка может возникать, когда файл заголовка определяет функцию, которая не является inline . Если включить этот заголовочный файл в более чем один исходный файл, вы получите несколько определений функции в исполняемом файле.
Ниже представлены возможные решения.
inline Добавьте ключевое слово в функцию:
Удалите тело функции из файла заголовка и оставьте только объявление, а затем реализуйте функцию в одном и только одном исходном файле:
Эта ошибка также может возникать при определении функций-членов вне объявления класса в файле заголовка:
Чтобы устранить эту проблему, переместите определения функций члена внутри класса. Функции-члены, определенные внутри объявления класса, неявно встроены.
Эта ошибка может возникать при связывании более одной версии стандартной библиотеки или CRT. Например, при попытке связать как розничную, так и отладочную библиотеки CRT либо статическую и динамическую версии библиотеки, или две различные версии стандартной библиотеки для исполняемого файла, эта ошибка может быть сообщена много раз. Чтобы устранить эту проблему, удалите все копии каждой библиотеки, кроме одной, из команды link. В одном исполняемом файле не рекомендуется смешивать библиотеки розничной и отладочной версий, а также разные версии библиотеки.
Чтобы указать компоновщику использовать библиотеки, отличные от параметров по умолчанию, в командной строке укажите используемые библиотеки и используйте параметр /NODEFAULTLIB , чтобы отключить библиотеки по умолчанию. В интегрированной среде разработки добавьте ссылки на проект, чтобы указать используемые библиотеки, а затем откройте диалоговое окно страницы свойств для проекта, а затем на странице компоновщика, входные свойства задайте значение игнорировать все библиотеки по умолчаниюили игнорировать определенные свойства библиотек по умолчанию, чтобы отключить библиотеки по умолчанию.
Эта ошибка может возникать, если при использовании параметра /CLR используется сочетание статических и динамических библиотек. Например, эта ошибка может возникнуть при создании библиотеки DLL для использования в исполняемом файле, который ссылается на статическую библиотеку CRT. Чтобы устранить эту проблему, используйте только статические библиотеки или только динамические библиотеки для всего исполняемого файла и для всех библиотек, которые вы создаете для использования в исполняемом файле.
Эта ошибка может возникать, если символ является упакованной функцией (созданной путем компиляции с параметром /Gy) и включен в несколько файлов, но был изменен между компиляциями. Чтобы устранить эту проблему, перекомпилируются все файлы, содержащие упакованную функцию.
Эта ошибка может возникать, если символ определен по-разному в двух объектах-членах в разных библиотеках и используются оба объекта-члена. Один из способов устранить эту проблему, если библиотеки статически связаны, — использовать объект-член только из одной библиотеки и сначала включить эту библиотеку в командную строку компоновщика. Чтобы использовать оба символа, необходимо создать способ их различения. Например, если вы можете построить библиотеки из источника, можно создать оболочку для каждой библиотеки в уникальном пространстве имен. Кроме того, можно создать новую библиотеку оболочек, использующую уникальные имена для переноса ссылок на одну из исходных библиотек, связать новую библиотеку с исходной библиотекой, а затем связать исполняемый объект с новой библиотекой вместо исходной библиотеки.
Эта ошибка может возникать, если extern const переменная определена дважды и имеет другое значение в каждом определении. Чтобы устранить эту проблему, определите константу только один раз или используйте пространства имен или enum class определения для различения констант.
Эта ошибка может возникать, если вы используете UUID. lib в сочетании с другими lib-файлами, определяющими идентификаторы GUID (например, OLEDB. lib и адсиид. lib). Например:
Чтобы устранить эту проблему, добавьте параметр /Force: Multiple в параметры командной строки компоновщика и убедитесь, что UUID. lib является первой библиотекой, на которую имеется ссылка.
Как избежать ошибки компоновщика lnk2005 для переменных, определенных в файле заголовка?
имейте в виду, что #include примерно так же, как вырезание и вставка включенного файла внутри исходного файла, который включает его (это грубая аналогия, но вы понимаете суть). Это означает, если у вас есть:
в файле заголовка, и этот файл заголовка включен тремя исходными файлами в программу, тогда все они будут иметь глобальное имя x, определенное, которое будет конфликтовать.
что вы хотите сделать, это определить переменную как extern, так что .cpp файлы будут заявление, а потом в одном из ваших .cpp файлы дают фактическое определение.
конечно, я бы рекомендовал против глобалов, но если вы должны использовать их, это удержит их от конфликта.
это потому, что компилятор компилирует каждый .cpp файл отдельно, создавая .obj файл для каждого из них. Ваш заголовок, похоже, имеет что-то вроде:
когда это включено в каждый из ваших трех вы получаете три копии int slider переменная, как если бы вы объявили ее в каждом . Компоновщик жалуется на это, потому что у вас нет трех разных вещей с одним и тем же именем.
что вы, вероятно, хотите сделать, это изменить файл заголовка, чтобы прочитать:
это говорит компилятору, что есть slider переменная где-то, но, возможно, не здесь, и позволяет компоновщику понять это. Затем в один :
дает компоновщику одну фактическую переменную для связи.
потому что «int slider» уже определен в другом файле? Проверьте, что у вас есть защита заголовка.
если он находится в нескольких единицах перевода, и вы хотите, чтобы переменные были разными (т. е. не глобальными), то, возможно, объявите их в анонимном пространстве имен:
Если вы хотите, чтобы они были глобальными, посмотрите на решение Джеймса.
что происходит, так это то, что каждая из переменных из переменных.h дается глобальная область для каждого из отдельных файлов C. Когда компоновщик собирает все файлы C, он видит несколько переменных с одинаковым именем.
Если вы хотите использовать переменные из файла заголовка в качестве глобальных переменных, вам придется использовать ключевое слово «extern» перед всеми из них, а в главном файле не используйте ключевое слово extern.
Вы можете создать две переменные файлов.h И EVariables.h, или просто объявите переменные в main.файл cpp.
гораздо лучший способ сделать это-создать класс переменных и передать ссылку на класс.
Я знаю, что это старый поток, но я наткнулся на это как один из первых результатов поиска от Google. Я решил проблему, поместив переменную static.
я попробовал extern и в моей ситуации, которая, похоже, не решила проблему.
этой ошибки связывания также можно избежать, если переменные включены несколько раз через «переменные».h » объявляются как const.
у меня тоже была эта ошибка, хотя я работаю с определениями extern. Проблема заключалась в инициализации переменных в определениях extern: