【问题标题】:Why am I getting a 'multiple definition' error? how do i fix it?为什么我收到“多重定义”错误?我如何解决它?
【发布时间】:2017-05-26 15:35:02
【问题描述】:

终端给出的命令:

g++ main.cpp test.cpp

错误信息:

/tmp/ccvgRjlI.o: 在函数 `test2()':
test.cpp:(.text+0x0): 多个 `test2()'的定义
/tmp/ccGvwiUE.o:main.cpp:(.text+0x0): 首先在这里定义
collect2:错误:ld 返回 1 个退出状态 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

【问题讨论】:

标签: c++ g++ linker-errors


【解决方案1】:

标头test.hpp 包含在两个编译单元中。第一个是编译单元main.cpp,第二个是编译单元test.cpp

默认情况下,函数具有外部链接。这意味着具有相同名称和签名的函数在不同的编译单元中表示相同的函数。它们应定义一次。但是在您的程序中,函数test2 的定义存在于两个编译单元中,并且链接器不知道要使用该函数的什么定义。

您可以将函数声明为内联函数。例如

inline void test2() { std::cerr << "test2" << std::endl; }

在这种情况下,它可以在每个编译单元中定义。

或者您可以只在标题中放置您使用函数test 所做的函数声明,并在例如test.cpp 中定义它。

另一种方法是将函数声明为具有内部链接。为此,您可以使用关键字 static

在标题中定义函数
static void test2() { std::cerr << "test2" << std::endl; }

或将其放置在未命名的命名空间中

namespace
{
    void test2() { std::cerr << "test2" << std::endl; }
}

在这种情况下,每个编译单元都有自己的函数test2

【讨论】:

    【解决方案2】:

    main.cpptest.cpp 都包含test.hpp,其中声明 void test()定义 void test2()。通过在两个实现文件中包含test.hpp,您将制作每个定义和声明的两个副本。您可以根据需要多次声明一个函数,但您只能定义一次。将 void test2() 的正文移动到单独的实现 (.cpp) 文件以解决链接器错误。

    【讨论】:

      【解决方案3】:

      你得到它是因为你在头文件中定义(实现)了非静态和非内联函数test2,并且你在两个源文件中都包含了头文件。这意味着该函数将在translation units 中定义。

      【讨论】:

        【解决方案4】:

        由于test.hpp 文件包含在main.cpptest.cpp 中,因此test2 函数有两种实现。所以链接器会产生错误。将函数实现移至test.cpp 文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-19
          相关资源
          最近更新 更多