当方法定义包含在多个翻译单元(也称为目标文件)中时,通常会发生这种情况。后来,当链接器组合这些目标文件时,它发现同一方法有多个定义,并抱怨因为它不知道使用哪一个。下面是一个如何引入此错误的简单示例:
有头文件header.hpp
包含方法声明及其定义:
class foo {
public:
void bar ();
};
void foo::bar ()
{
}
并有两个源文件 source1.cpp 和 source2.cpp 都包含该文件:
source1.cpp
:
#include "header1.hpp"
int example1()
{
foo f;
f.bar ();
}
... and source2.cpp
:
#include "header1.hpp"
int main ()
{
foo f;
f.bar ();
f.bar ();
}
然后,分别编译两个文件并将它们链接在一起。例如:
g++ -c source1.cpp source1.o
g++ -c source2.cpp source2.o
g++ -o a.out source1.o source2.o
这会给你一个你在问题中描述的链接器错误,因为方法foo::bar
在 source1 和 source2 对象中出现两次。链接器不知道该使用哪一个。
此问题有两种常见的解决方案:
解决方案#1 - 内联该方法。
通过声明该方法inline
关键字,编译器将内联整个方法,或者,如果决定不内联,它将生成匿名方法(相同的方法,但对于给定的目标文件具有一些唯一的名称),因此目标文件中不会发生冲突。例如:
class foo {
public:
void bar ();
};
inline void foo::bar ()
{
}
解决方案#2 - 在另一个源文件中定义(实现)该方法,以便它在整个程序中仅出现一次。例如:
header1.hpp
:
class foo {
public:
void bar ();
};
header1.cpp
:
#include "header1.hpp"
void foo::bar ()
{
}
要决定是否内联,您必须知道(或至少猜测)调用此函数是否比在整个程序中重复/内联此代码更昂贵。内联代码通常会使您的程序变得更大并增加编译时间。但这并不一定会使速度更快。另外,在源文件中有定义不会导致使用该函数重新编译所有源文件,而只会重新编译有定义的源文件,然后重新链接。许多程序员对 C++ 内联感到疯狂,但没有真正理解它如何影响程序。我建议仅在调用该函数成为性能瓶颈时才使用源文件中的定义并将其内联,否则将其内联将修复它。
希望能帮助到你。快乐编码!