Как избежать ошибки компоновщика lnk2005 для переменных, определенных в файле заголовка?

у меня есть 3 cpp-файла, которые выглядят так

#include "Variables.h"
void AppMain() {
    //Stuff...
}

все они используют одни и те же переменные внутри них, поэтому у них одинаковые заголовки, но я получаю такие вещи

1>OnTimer.obj : error LNK2005: "int slider" (?slider@@3HA) already defined in AppMain.obj

почему это?

7 ответов


имейте в виду, что #include примерно так же, как вырезание и вставка включенного файла внутри исходного файла, который включает его (это грубая аналогия, но вы понимаете суть). Это означает, если у вас есть:

int x;  // or "slider" or whatever vars are conflicting

в файле заголовка, и этот файл заголовка включен тремя исходными файлами в программу, тогда все они будут иметь глобальное имя x, определенное, которое будет конфликтовать.

что вы хотите сделать, это определить переменную как extern, так что .cpp файлы будут заявление, а потом в одном из ваших .cpp файлы дают фактическое определение.

в переменные.h:

extern int x;

В SomeSourceFile.cpp

int x;

конечно, я бы рекомендовал против глобалов, но если вы должны использовать их, это удержит их от конфликта.


это потому, что компилятор компилирует каждый .cpp файл отдельно, создавая .obj файл для каждого из них. Ваш заголовок, похоже, имеет что-то вроде:

int slider;

когда это включено в каждый из ваших трех вы получаете три копии int slider переменная, как если бы вы объявили ее в каждом . Компоновщик жалуется на это, потому что у вас нет трех разных вещей с одним и тем же именем.

что вы, вероятно, хотите сделать, это изменить файл заголовка, чтобы прочитать:

extern int slider;

это говорит компилятору, что есть slider переменная где-то, но, возможно, не здесь, и позволяет компоновщику понять это. Затем в один :

int slider;

дает компоновщику одну фактическую переменную для связи.


потому что "int slider" уже определен в другом файле? Проверьте, что у вас есть защита заголовка...

#ifndef _VARIABLES_H_
#define _VARIABLES_H_

int slider;

#endif

если он находится в нескольких единицах перевода, и вы хотите, чтобы переменные были разными (т. е. не глобальными), то, возможно, объявите их в анонимном пространстве имен:

namespace {
    int slider;
}

Если вы хотите, чтобы они были глобальными, посмотрите на решение Джеймса.


что происходит, так это то, что каждая из переменных из переменных.h дается глобальная область для каждого из отдельных файлов C. Когда компоновщик собирает все файлы C, он видит несколько переменных с одинаковым именем.

Если вы хотите использовать переменные из файла заголовка в качестве глобальных переменных, вам придется использовать ключевое слово "extern" перед всеми из них, а в главном файле не используйте ключевое слово extern.

главная c:

int n_MyVar;

другие файлы:

extern int n_MyVar;

Вы можете создать две переменные файлов.h И EVariables.h, или просто объявите переменные в main.файл cpp.

гораздо лучший способ сделать это-создать класс переменных и передать ссылку на класс.


Я знаю, что это старый поток, но я наткнулся на это как один из первых результатов поиска от Google. Я решил проблему, поместив переменную static.

namespace Vert
{
   static int i;
}

я попробовал extern и в моей ситуации, которая, похоже, не решила проблему.


этой ошибки связывания также можно избежать, если переменные включены несколько раз через "переменные".h " объявляются как const.


у меня тоже была эта ошибка, хотя я работаю с определениями extern. Проблема заключалась в инициализации переменных в определениях extern:

ID3D11VertexShader*         g_pVertexShader = nullptr;
...
extern ID3D11VertexShader*  g_pVertexShader = nullptr;  // here's the problem 

=> ошибка

ID3D11VertexShader*         g_pVertexShader = nullptr;
...
extern ID3D11VertexShader*  g_pVertexShader;           // without initializing  

=> нет ошибок, проблема решена