如何避免头文件中定义的变量的LNK2005链接器错误?

时间:2011-04-07 00:28:10

标签: c++ header include linker-errors

我有3个cpp文件,看起来像这样

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

他们都在里面使用相同的变量,所以他们有相同的标题,但我得到像这样的东西

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

为什么?

7 个答案:

答案 0 :(得分:16)

请记住,#include大致类似于剪切和粘贴包含它的源文件中包含的文件(这是一个粗略的类比,但你明白了)。这意味着如果你有:

int x;  // or "slider" or whatever vars are conflicting
在头文件中

并且该头文件被程序中的三个源文件包含在内,那么它们都将具有一个将被冲突的全局命名x。

你想要做的是将变量定义为extern,以便.cpp文件都将获得声明,然后在一个.cpp文件中给出实际的定义。

在Variables.h中:

extern int x;
在SomeSourceFile.cpp中

int x;

当然,我建议不要使用全局变量,但如果你必须使用它们,这将使它们不会发生冲突。

答案 1 :(得分:3)

因为“int slider”已经在另一个文件中定义了?检查你是否有头部防护......

#ifndef _VARIABLES_H_
#define _VARIABLES_H_

int slider;

#endif

如果它跨越多个翻译单元,并且您确实希望变量不同(即不是全局变量),那么可以在匿名名称空间中声明它们:

namespace {
    int slider;
}

如果你确实希望它们具有全球性,那就看看詹姆斯的解决方案。

答案 2 :(得分:3)

这是因为编译器分别编译每个.cpp文件,为每个文件创建一个.obj文件。您的标题似乎包含:

int slider;

当这三个.cpp文件中包含此内容时,您将获得int slider变量的三个副本,就像您在每个.cpp变量中声明它一样1}}文件。链接器抱怨这个,因为你没有三个同名的东西。

您可能想要做的是将头文件更改为:

extern int slider;

这告诉编译器某处有一个slider变量,但可能不在这里,并让链接器弄清楚它。然后,在一个 .cpp文件中:

int slider;

为链接器提供一个实际变量来链接。

答案 3 :(得分:1)

正在发生的是,Variables.h中的每个变量都为每个单独的c文件提供了全局范围。当链接器编译所有c文件时,它会看到多个具有相同名称的变量。

如果您想将头文件中的变量用作全局变量,则必须在所有变量前面使用关键字“extern”,并且在主文件中不要使用关键字extern。< / p>

主要c:

int n_MyVar;

其他档案:

extern int n_MyVar;

您可以创建两个文件Variables.h和EVariables.h,或者只在main.cpp文件中声明变量。

更好的方法是创建一个Variables类并传递对该类的引用。

答案 4 :(得分:1)

我知道这是一个旧帖子,但我发现这是Google首批搜索结果之一。我通过将变量静态放置来解决问题。

namespace Vert
{
   static int i;
}

我尝试了extern,在我的情况下似乎没有解决问题。

答案 5 :(得分:0)

如果通过“Variables.h”多次包含的变量被声明为const,也可以避免这种链接错误。

答案 6 :(得分:0)

虽然我使用extern定义,但我也遇到了这个错误。问题是初始化外部定义中的变量:

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

=&GT;错误

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

=&GT;没有错误,问题解决了