错误LNK2005,已经定义了?

我在Win32控制台应用程序中有两个文件,A.cpp和B.cpp。

这两个文件只包含以下两行代码:

#include "stdafx.h" int k; 

编译时会产生错误

 Error 1 error LNK2005: "int k" (?a@@3HA) already defined in A.obj 

我不明白发生了什么事。

有人可以向我解释这个吗?

为什么这个错误?

你打破了一个定义规则 ,因此链接错误。

build议解决scheme


如果在两个cpp文件中需要相同的命名variables,则需要使用无名称命名空间(匿名命名空间)来避免该错误。

 namespace { int k; } 

如果你需要在多个文件中共享相同的variables,那么你需要使用extern

 extern int k; 

A.cpp

 #include "Ah" int k = 0; 

B.cpp

 #include "Ah" //Use `k` anywhere in the file 

将/ FORCE:MULTIPLE添加到链接器命令行选项。

从MSDN :“使用/ FORCE:MULTIPLE创build一个输出文件,无论LINK是否find一个符号的多个定义”。

如果你想同时引用同一个variables,其中一个应该有int k; 另外一个应该有extern int k;

对于这种情况,通常将定义( int k; )放在一个.cpp文件中,并将该声明( extern int k; )放在标题中,以便在需要访问该variables的位置包含该标题。

如果你希望每个k都是一个单独的variables,只是碰巧有相同的名字,你可以把它们标记为static ,比如: static int k; (在所有文件中,或者至less除了一个文件外)。 或者,您可以使用匿名命名空间:

 namespace { int k; }; 

同样,最多只有一个文件。

在C中,编译器通常不太挑剔。 具体来说,C有一个“暂定义”的概念,所以如果你有像int k;这样的东西int k; 两次(在相同或不同的源文件中)每个都将被视为暂时的定义,并且两者之间不会有冲突。 然而,这可能有点令人困惑,因为你仍然不能有两个包含初始化符的定义 – 带有初始化符的定义总是一个完整的定义,而不是一个试探性的定义。 换句话说, int k = 1; 出现两次将是一个错误,但int k; 在一个地方int k = 1; 在另一个不会。 在这种情况下, int k; 将被视为暂定义,并且int k = 1; 作为一个定义(和两个引用相同的variables)。

假设你想让'k'在不同的.cpp文件中成为一个不同的值(因此声明两次),请尝试将这两个文件更改为

 namespace { int k; } 

这保证名字'k'在翻译单位中唯一标识'k'。 旧版本的static int k; 已弃用。

如果你想让它们指向相同的值,把其中一个改为extern int k;

两个文件都将variablesk定义为整数( int )。

因此,链接器会看到两个具有相同名称的variables,并且如果您引用了k ,则不确定应该使用哪个variables。

要解决此问题,请将其中一个声明更改为:

 extern int k; 

这意味着: “k是一个整数,在这里声明,但在外部定义(即另一个文件)”。

现在只有一个variablesk ,可以由两个不同的文件适当引用。

如果你想让这些翻译单元共享这个variables,定义int k; 在A.cpp中并把extern int k; 在B.cpp中。

链接器告诉你有多次定义的variablesk 。 事实上,你在A.cpp中有一个定义,在B.cpp中有另一个定义。 这两个编译单元都会生成一个链接器用来创build程序的相应对象文件。 问题是,在你的情况下,链接器不知道要使用k定义。 在C ++中,你可以只有一个定义相同的结构(variables,types,函数)。

要解决它,你将不得不决定你的目标是什么

  • 如果你想有两个variables,都命名为k ,你可以在两个.cpp文件中使用一个匿名命名空间,然后像现在这样引用k

 namespace { int k; } 
  • 你可以重新命名其中的一个,从而避免重复的定义。
  • 如果你只想定义一个k并在.cpp文件中使用它,你需要声明为extern int k; ,并保持原样。 这将告诉链接器在这两种情况下使用一个定义(不变的版本) – extern意味着variables是在另一个编译单元中定义的。