错误 LNK2005:已定义 - C++
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/622229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error LNK2005: already defined - C++
提问by Navaneeth K N
Background
背景
I have a project named PersonLibrarywhich has two files.
我有一个名为PersonLibrary的项目,它有两个文件。
- Person.h
- Person.cpp
- 人.h
- 个人.cpp
This library produces a static library file. Another project is TestProjectwhich uses the PersonLibrary(Added though project dependencies in VS008). Everything worked fine until I added a non-member function to Person.h. Person.hlooks like
该库生成静态库文件。另一个项目是TestProject,它使用PersonLibrary(通过 VS008 中的项目依赖项添加)。一切正常,直到我向Person.h添加了一个非成员函数。Person.h看起来像
class Person
{
public:
void SetName(const std::string name);
private:
std::string personName_;
};
void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
Person.cppdefines SetNamefunction. When I try to use SetPersonNamefrom TestProject, I get error LNK2005: already defined. Here is how I used it
Person.cpp定义了SetName函数。当我尝试从TestProject使用SetPersonName时,出现错误 LNK2005: already defined。这是我如何使用它
#include "../PersonLibrary/Person.h"
int main(int argc, char* argv[])
{
Person person;
SetPersonName(person, "Bill");
return 0;
}
Workarounds tried
尝试的解决方法
1 - I have removed the Person.cppand defined the whole class in Person.h. Error gone and everything worked.
1 - 我删除了Person.cpp并在Person.h 中定义了整个类。错误消失了,一切正常。
2 - Changed the SetPersonNamemodifier to static. Like the below
2 - 将SetPersonName修饰符更改为static。像下面这样
static void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
Questions
问题
- Why the code shown first is not working as I expected?
- What difference staticmade here?
- What is the approapriate solution for this problem?
- 为什么首先显示的代码没有按我预期的那样工作?
- 静态在这里有什么区别?
- 这个问题的适当解决方案是什么?
Thanks
谢谢
回答by dirkgently
You either have to
你要么必须
- move
SetPersonName
's definition to a .cpp file, compile and link to the resulting target - make
SetPersonName
inline
- move
SetPersonName
的定义到 .cpp 文件,编译并链接到生成的目标 - 化妆
SetPersonName
在线
This is a well known case of One Definition Rule violation.
这是一个众所周知的违反单一定义规则的案例。
The static keyword makes the function's linkage internal i.e. only available to the translation unit it is included in. This however is hiding the real problem. I'd suggest move the definition of the function to its own implementation file but keep the declaration in the header.
static 关键字使函数的链接成为内部的,即仅对包含它的翻译单元可用。然而,这隐藏了真正的问题。我建议将函数的定义移动到它自己的实现文件中,但将声明保留在标题中。
回答by Logan Capaldo
When you compile you're library, its lib file contains a definition for SetPersonName. When you compile your program that uses the library, since it includes the header, and you've written the code inline in the header it also compiles in a definition for SetPersonName. Two definitions for the same function aren't (generally) allowed. The static keyword tells the compiler that the function shouldn't be exposed outside of the current translation unit (discrete piece of code you are compiling), so the definition in the library isn't visible to the linker.
当你编译你的库时,它的 lib 文件包含一个 SetPersonName 的定义。当您编译使用该库的程序时,因为它包含头文件,并且您已经在头文件中编写了内联代码,它还会在 SetPersonName 的定义中进行编译。同一函数的两个定义(通常)是不允许的。static 关键字告诉编译器该函数不应暴露在当前翻译单元(您正在编译的离散代码段)之外,因此库中的定义对链接器不可见。
The appropriate solution to this problem depends on your goals. Header files with static function declarations is almost never what you want. From a design standpoint I would recommend getting rid of SetPersonName altogether, and just use Person::SetName.
此问题的适当解决方案取决于您的目标。带有静态函数声明的头文件几乎从来都不是你想要的。从设计的角度来看,我建议完全摆脱 SetPersonName,而只使用 Person::SetName。
However, failing that, I would implement it much like you've done for the rest of your functionality, declarations in the header, and implementation in the .cpp. Inline functions associated with a library will tend to diminish many of the advantages of using a library in the first place.
但是,如果失败了,我会像您对其余功能、标头中的声明和 .cpp 中的实现所做的一样来实现它。与库相关的内联函数往往会削弱使用库的许多优势。
回答by epatel
The function SetPersonName will be compiled into each objectfile that includes the Person.h file, thus making the linker seeing several functions and giving the error.
By writing static you state that the function will only be visible within a single objectfile. You will still get several functions in you binary but now you will not get the errors.
Try to write
inline
before the function likeinline void SetPersonName(Person& person,const std::string name) { person.SetName(name); }
...because the function is pretty simple it is OK I think to have it as an inline. An inline will place the necessary code where the function is used, without actually creating a function to be called.
函数 SetPersonName 将被编译到包含 Person.h 文件的每个目标文件中,从而使链接器看到多个函数并给出错误。
通过编写 static 您声明该函数仅在单个目标文件中可见。你仍然会在你的二进制文件中得到几个函数,但现在你不会得到错误。
尝试
inline
在函数之前写inline void SetPersonName(Person& person,const std::string name) { person.SetName(name); }
...因为该函数非常简单,所以我认为可以将其作为内联函数使用。内联将在使用函数的地方放置必要的代码,而不实际创建要调用的函数。
回答by Rob Walker
By declaring the function static you are scoping it to the current translation unit, so in effect you have added a new SetPersonName function in your main file, and would be calling that not the one defined in the library.
通过将函数声明为 static,您将其范围限定为当前翻译单元,因此实际上您已在主文件中添加了一个新的 SetPersonName 函数,并且将调用该函数而不是库中定义的函数。
The correct solution is to declare SetPersonName as extern in person.h and implement it in person.cpp
正确的解决方法是在person.h中将SetPersonName声明为extern并在person.cpp中实现
Person.h
人.h
extern void SetPersonName(Person& person,const std::string name);
Person.cpp
个人.cpp
void SetPersonName(Person& person,const std::string name)
{
person.SetName(name);
}
回答by Geo
A solution would be to make that function a static method. That will stop the "already defined" errors.
一种解决方案是使该函数成为静态方法。这将停止“已定义”错误。
回答by Paul
I had a similar situation as described clearly by @logan-capaldo above.
我遇到了类似的情况,正如上面@logan-capaldo 清楚地描述的那样。
A CPP source file (myfile.cpp) contained a function MyFunction. When building, this got compiled into myfile.obj. But the main CPP file (main.cpp) also included myfile.cpp, so the function MyFunction was being included/compiled/linked twice, leading to the "LNK2005 already defined" error.
CPP 源文件 (myfile.cpp) 包含一个函数 MyFunction。在构建时,它被编译到 myfile.obj 中。但是主 CPP 文件(main.cpp)也包含 myfile.cpp,因此函数 MyFunction 被包含/编译/链接两次,导致“LNK2005 已定义”错误。
This is messy but I didn't have time to fix it properly. The quickest fix (in VS Express 2012) was to right-click myfile.cpp in Solution Explorer, go to Properties and change Excluded From Build to Yes. I guess this prevents one of the OBJ files from being created and/or linked and so removes the error.
这很乱,但我没有时间正确修复它。最快的解决方法(在 VS Express 2012 中)是在解决方案资源管理器中右键单击 myfile.cpp,转到“属性”并将“从构建中排除”更改为“是”。我想这会阻止创建和/或链接 OBJ 文件之一,从而消除错误。
回答by Clifton Roberts
For anyone landing here dealing with this error in a Qt project, make sure you don't have any non-signal functions defined under signals:
in your header files.
对于在 Qt 项目中处理此错误的任何人,请确保您signals:
的头文件中没有定义任何非信号函数。
Incorrect, throws LNK2005
on Foo::promiseData()
:
不正确,投LNK2005
上Foo::promiseData()
:
class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject* parent = nullptr);
signals:
void dataReady(QList<QObject*> data) const;
void promiseData() const; // <-- This function is not supposed to be a signal.
Correct:
正确的:
class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject* parent = nullptr);
void promiseData() const;
signals:
void dataReady(QList<QObject*> data) const;