问题
我是C++的新手,我正在做一个作业问题,该问题在控制台中绘制了各种分布,但是我的项目无法编译。当我将所有文件都保存在同一个文件中时,它们都可以正常工作,但我的教授希望我们将其拆分为hpp文件,cpp文件和主文件。我只是移动了所有内容,现在由于重复的符号错误而无法编译。
定义与声明
我知道您只想在头文件中包含函数的声明,因此我添加了这些声明,但将函数的实际定义保留在cpp文件中。我在cpp文件中有一个include语句,其中包括头文件,而在main.cpp中有另一个声明,其中包括cpp文件。
我知道我的问题可能与我的include语句有关,但是我对如何解决它迷失了。
distributions.hpp
这个文件是我编写的四个函数的类定义和声明

#include <iostream>

class DistributionPair
{
  public:
    DistributionPair(std::uint32_t minValue, std::uint32_t maxValue) :
        minValue(minValue),
        maxValue(maxValue),
        count(0)
    {
    }

    std::uint32_t minValue;
    std::uint32_t maxValue;
    std::uint32_t count;
};

std::vector<DistributionPair> generateUniformDistribution(std::uint32_t, std::uint32_t, std::uint32_t, std::uint8_t);
std::vector<DistributionPair> generateNormalDistribution(std::uint32_t, float, float, std::uint8_t);
std::vector<DistributionPair> generatePoissonDistribution(std::uint32_t, std::uint8_t, std::uint8_t);
void plotDistribution(std::string, const std::vector<DistributionPair>&, const std::uint8_t);
distributions.cpp
该文件包含这四个功能的其余定义
#include <iostream>
#include <iomanip>
#include <random>
#include "distributions.hpp"

std::vector<DistributionPair> generateUniformDistribution(std::uint32_t howMany, std::uint32_t min, std::uint32_t max, std::uint8_t numBins)
{......
main.cpp
这是绘制分布图的主要功能
#include <iostream>
#include "distributions.cpp"

int main()
{......
错误讯息
以下是我在编译代码时收到的错误消息:
duplicate symbol 'generateUniformDistribution(unsigned int, unsigned int, unsigned int, unsigned char)' in:
    /Users/ryanegbert/Desktop/c++/assign2/build/RandDistributions.build/Debug/RandDistributions.build/Objects-normal/x86_64/distributions.o
    /Users/ryanegbert/Desktop/c++/assign2/build/RandDistributions.build/Debug/RandDistributions.build/Objects-normal/x86_64/main.o
..........

ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
如果我使用#include "distributions.hpp",则会收到另一个编译错误:
/Users/ryanegbert/Desktop/c++/assign2/main.cpp:6:20: error: implicit instantiation of undefined template 'std::__1::vector<DistributionPair, std::__1::allocator<DistributionPair> >'
    auto uniform = generateUniformDistribution(100000, 0, 79, 40);
因为我的功能是在distributions.cpp中定义的。
我在Mac上使用Xcode v11.0。
有人对我为什么会出现此编译错误有任何帮助吗?

最佳答案

请注意,这是链接器错误,而不是编译器错误。

将可执行文件构建视为两个阶段的过程。

  • 第一步,编译器读取源代码并生成.o文件。
  • 在第二阶段,链接器读取.o(和其他)文件并生成可执行文件。

  • .o文件具有二进制代码和符号引用。编译器生成两种东西:具有已定义函数的二进制代码和具有已声明但未定义的函数的符号引用。链接器任务是解决所有引用,即,将所有符号引用与二进制代码相关联,以构建完整的可执行文件。

    在您的示例中似乎发生的事情是您的构建脚本正在执行以下操作:
  • 将'main.cpp'+'distributions.cpp'(包含)编译为'main.o'
  • 将'distributions.cpp'编译为'distributions.o'
  • 将'main.o'+'distributions.o'链接到最终的可执行文件


  • 这样,链接器就具有来自distributions.cpp的已编译代码的两个副本,一个在main.o中,另一个在distributions.o中。

    要解决此问题,您必须执行以下一项操作:
  • 指示链接器仅使用“main.o”来创建可执行文件

  • 要么,
  • 将#include“distributions.cpp”替换为#include“distributions.hpp”,以便您的main.o文件将仅包含符号引用,并且链接程序会将来自distributions.o的符号和代码粘合到可执行文件中。
  • 10-04 14:40