错误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是在另一个编译单元中定义的。