为什么我会收到 'multiple definition' 错误?我如何解决它?
Why am I getting a 'multiple definition' error? how do i fix it?
终端给出的命令:
g++ main.cpp test.cpp
错误信息:
/tmp/ccvgRjlI.o: In function `test2()':
test.cpp:(.text+0x0): multiple
definition of `test2()'
/tmp/ccGvwiUE.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
main.cpp
源代码:
#include "test.hpp"
int main(int argc, char *argv[])
{
test2();
return 0;
}
test.hpp
#ifndef _TEST_HPP_
#define _TEST_HPP_
#include <iostream>
void test();
void test2() { std::cerr << "test2" << std::endl; }
#endif
test.cpp
#include "test.hpp"
using std::cerr;
using std::endl;
void test() { cerr << "test" << endl; }
顺便说一下,下面的编译很好:
g++ main.cpp
由于 test.hpp
文件同时包含在 main.cpp
和 test.cpp
中,因此 test2
函数有两个实现。因此链接器会产生错误。将函数实现移动到 test.cpp
文件。
你得到它是因为你在头文件中定义(实现)了非静态和非内联函数test2
,并且你在两个源文件中都包含了头文件。这意味着该函数将在 translation units.
中定义
main.cpp
和 test.cpp
都包含 test.hpp
,其中 声明 void test()
和 定义 void test2()
。通过在两个实现文件中包含 test.hpp
,您为每个定义和声明制作了两份副本。您可以根据需要多次声明一个函数,但只能定义一次。将 void test2()
的主体移动到单独的实现 (.cpp) 文件以解决链接器错误。
header test.hpp
包含在两个编译单元中。第一个是编译单元main.cpp
,第二个是编译单元test.cpp
.
函数默认有外部链接。这意味着具有相同名称和签名的函数在不同的编译单元中表示相同的函数。它们应被定义一次。但是在您的程序中,函数 test2
的定义存在于两个编译单元中,链接器不知道要使用什么函数定义。
您可以将函数声明为内联函数。例如
inline void test2() { std::cerr << "test2" << std::endl; }
在这种情况下,可以在每个编译单元中定义。
或者您可以在 header 中仅放置您使用函数 test
所做的函数声明,并在 test.cpp
.
中定义它
另一种方法是将函数声明为具有内部链接。为此,您可以使用关键字 static
在 header 中定义函数
static void test2() { std::cerr << "test2" << std::endl; }
或将其放在未命名的名称中space
namespace
{
void test2() { std::cerr << "test2" << std::endl; }
}
在这种情况下,每个编译单元都有自己的函数test2
。
终端给出的命令:
g++ main.cpp test.cpp
错误信息:
/tmp/ccvgRjlI.o: In function `test2()':
test.cpp:(.text+0x0): multiple definition of `test2()'
/tmp/ccGvwiUE.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status main.cpp
源代码:
#include "test.hpp"
int main(int argc, char *argv[])
{
test2();
return 0;
}
test.hpp
#ifndef _TEST_HPP_
#define _TEST_HPP_
#include <iostream>
void test();
void test2() { std::cerr << "test2" << std::endl; }
#endif
test.cpp
#include "test.hpp"
using std::cerr;
using std::endl;
void test() { cerr << "test" << endl; }
顺便说一下,下面的编译很好:
g++ main.cpp
由于 test.hpp
文件同时包含在 main.cpp
和 test.cpp
中,因此 test2
函数有两个实现。因此链接器会产生错误。将函数实现移动到 test.cpp
文件。
你得到它是因为你在头文件中定义(实现)了非静态和非内联函数test2
,并且你在两个源文件中都包含了头文件。这意味着该函数将在 translation units.
main.cpp
和 test.cpp
都包含 test.hpp
,其中 声明 void test()
和 定义 void test2()
。通过在两个实现文件中包含 test.hpp
,您为每个定义和声明制作了两份副本。您可以根据需要多次声明一个函数,但只能定义一次。将 void test2()
的主体移动到单独的实现 (.cpp) 文件以解决链接器错误。
header test.hpp
包含在两个编译单元中。第一个是编译单元main.cpp
,第二个是编译单元test.cpp
.
函数默认有外部链接。这意味着具有相同名称和签名的函数在不同的编译单元中表示相同的函数。它们应被定义一次。但是在您的程序中,函数 test2
的定义存在于两个编译单元中,链接器不知道要使用什么函数定义。
您可以将函数声明为内联函数。例如
inline void test2() { std::cerr << "test2" << std::endl; }
在这种情况下,可以在每个编译单元中定义。
或者您可以在 header 中仅放置您使用函数 test
所做的函数声明,并在 test.cpp
.
另一种方法是将函数声明为具有内部链接。为此,您可以使用关键字 static
在 header 中定义函数static void test2() { std::cerr << "test2" << std::endl; }
或将其放在未命名的名称中space
namespace
{
void test2() { std::cerr << "test2" << std::endl; }
}
在这种情况下,每个编译单元都有自己的函数test2
。