【问题标题】:How can I avoid the LNK2005 linker error for variables defined in a header file?对于头文件中定义的变量,如何避免 LNK2005 链接器错误?
【发布时间】:2026-02-13 23:05:02
【问题描述】:

我有 3 个类似这样的 cpp 文件

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

它们都在其中使用相同的变量,因此它们具有相同的标题,但我得到了这样的东西

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

为什么会这样?

【问题讨论】:

  • 将“extern”放在 .h 文件中变量声明的前面。并在其中一个 .cpp 文件中定义它们。考虑改用类。

标签: c++ header include linker-errors


【解决方案1】:

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

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

在头文件中,并且该头文件被程序中的三个源文件包含,那么它们都将定义一个名为 x 的全局名称,这将发生冲突。

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

在变量.h 中:

extern int x;

在 SomeSourceFile.cpp 中

int x;

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

【讨论】:

    【解决方案2】:

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

    int slider;
    

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

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

    extern int slider;
    

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

    int slider;
    

    给链接器一个要链接的实际变量。

    【讨论】:

      【解决方案3】:

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

      #ifndef _VARIABLES_H_
      #define _VARIABLES_H_
      
      int slider;
      
      #endif
      

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

      namespace {
          int slider;
      }
      

      如果您确实希望它们具有全局性,请查看 James 的解决方案。

      【讨论】:

      • 标题保护在这里没有帮助,因为 cpp 文件是单独编译的。
      • 我对此给出了解决方案。检查固定答案。
      • @Mark:虽然使用namespace编译,但它可能无法满足您的要求。如果您希望在所有源文件中使用相同的变量(以便一个文件中的更改在另一个文件中可见),上述解决方案不会这样做。
      • 是的,如果你希望每个 .cpp 文件都有独立的滑块变量,使用这个解决方案,如果你希望所有的 .cpp 文件共享同一个滑块变量,使用下面的 extern 方法。跨度>
      • 是的,我需要使用相同的值...更改了接受的答案
      【解决方案4】:

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

      如果你想使用头文件中的变量作为全局变量,那么你必须在它们前面使用关键字“extern”,并且在主文件中不要使用关键字extern。

      主c:

      int n_MyVar;
      

      其他文件:

      extern int n_MyVar;
      

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

      一个更好的方法是创建一个变量类并将引用传递给该类。

      【讨论】:

        【解决方案5】:

        我知道这是一个旧线程,但我是在 Google 的第一批搜索结果中发现的。我通过放置变量静态解决了这个问题。

        namespace Vert
        {
           static int i;
        }
        

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

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

            => 错误

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

            =>没有错误,问题解决了

            【讨论】:

              最近更新 更多