c++ - 包括问题 : 'multiple definition' , 'first defined here'

标签 c++

我有三个文件:

main.cpp
MyClass.cpp
MyClass.hpp

我有一个库头文件,"testLib.hpp",我想将它包含在 MyClass.hpp 中,这样我就可以让 testLib 的对象之一成为类属性。

我将 MyClass.hpp 包含在 MyClass.cppmain.cpp 中。尝试编译项目时,出现以下错误

MyClass.cpp   multiple definition of 'testLib::testLib::function1()
obj/Release/main.o:main.cpp first defined here
MyClass.cpp   multiple definition of 'testLib::testLib::function2()
obj/Release/main.o:main.cpp first defined here

等等。

main.cppMyClass.cpp 都包含MyClass.hpp(其中包含testLib.hpp) .从错误判断,看起来 MyClass.cpp 在库函数已经被 main.cpp 包含之后试图包含它们。但是,我在 MyClass.hpp 中包含了守卫,所以我不明白它是如何尝试两次包含 MyClass.hpp 的。

代码如下:

我的类.hpp

#ifndef THIS_HEADER_H
#define THIS_HEADER_H

#include <stdint.h>
#include <iostream>
#include "testLib/testLib.hpp"

class MyClass
{

public:
    void test();
    int foo;

private:
    uint32_t bar;
    //I want to include an object from the library as part of this class
    //TestLib::Device device;
};

#endif

我的类.cpp

#include <stdio.h>
#include "MyClass.hpp"

void MyClass::test()
{

}

主要.cpp

#include <iostream>
#include "MyClass.hpp"

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    return 0;
}

如有任何帮助,我们将不胜感激!

编辑 我试图隐藏实际的文件名以使问题更加笼统和清晰,但似乎问题可能是由我没有写的“testLib.hpp”引起的。该文件实际上是以下“sweep.hpp”文件。对于此文件中的每个公共(public)函数,我都收到了“此处的多重定义/首次定义”错误:

扫描.hpp

#ifndef SWEEP_DC649F4E94D3_HPP
#define SWEEP_DC649F4E94D3_HPP

/*
 * C++ Wrapper around the low-level primitives.
 * Automatically handles resource management.
 *
 * sweep::sweep  - device to interact with
 * sweep::scan   - a full scan returned by the device
 * sweep::sample - a single sample in a full scan
 *
 * On error sweep::device_error gets thrown.
 */

#include <cstdint>
#include <memory>
#include <stdexcept>
#include <vector>

#include <sweep/sweep.h>

namespace sweep {

// Error reporting

struct device_error final : std::runtime_error {
  using base = std::runtime_error;
  using base::base;
};

// Interface

struct sample {
  const std::int32_t angle;
  const std::int32_t distance;
  const std::int32_t signal_strength;
};

struct scan {
  std::vector<sample> samples;
};

class sweep {
public:
  sweep(const char* port);
  sweep(const char* port, std::int32_t bitrate);
  void start_scanning();
  void stop_scanning();
  bool get_motor_ready();
  std::int32_t get_motor_speed();
  void set_motor_speed(std::int32_t speed);
  std::int32_t get_sample_rate();
  void set_sample_rate(std::int32_t speed);
  scan get_scan();
  void reset();

private:
  std::unique_ptr<::sweep_device, decltype(&::sweep_device_destruct)> device;
};

// Implementation

namespace detail {
struct error_to_exception {
  operator ::sweep_error_s*() { return &error; }

  ~error_to_exception() noexcept(false) {
    if (error) {
      device_error e{::sweep_error_message(error)};
      ::sweep_error_destruct(error);
      throw e;
    }
  }

  ::sweep_error_s error = nullptr;
};
}

sweep::sweep(const char* port)
    : device{::sweep_device_construct_simple(port, detail::error_to_exception{}), &::sweep_device_destruct} {}

sweep::sweep(const char* port, std::int32_t bitrate)
    : device{::sweep_device_construct(port, bitrate, detail::error_to_exception{}), &::sweep_device_destruct} {}

void sweep::start_scanning() { ::sweep_device_start_scanning(device.get(), detail::error_to_exception{}); }

void sweep::stop_scanning() { ::sweep_device_stop_scanning(device.get(), detail::error_to_exception{}); }

bool sweep::get_motor_ready() { return ::sweep_device_get_motor_ready(device.get(), detail::error_to_exception{}); }

std::int32_t sweep::get_motor_speed() { return ::sweep_device_get_motor_speed(device.get(), detail::error_to_exception{}); }

void sweep::set_motor_speed(std::int32_t speed) {
  ::sweep_device_set_motor_speed(device.get(), speed, detail::error_to_exception{});
}

std::int32_t sweep::get_sample_rate() { return ::sweep_device_get_sample_rate(device.get(), detail::error_to_exception{}); }

void sweep::set_sample_rate(std::int32_t rate) {
  ::sweep_device_set_sample_rate(device.get(), rate, detail::error_to_exception{});
}

scan sweep::get_scan() {
  using scan_owner = std::unique_ptr<::sweep_scan, decltype(&::sweep_scan_destruct)>;

  scan_owner releasing_scan{::sweep_device_get_scan(device.get(), detail::error_to_exception{}), &::sweep_scan_destruct};

  auto num_samples = ::sweep_scan_get_number_of_samples(releasing_scan.get());

  scan result;
  result.samples.reserve(num_samples);

  for (std::int32_t n = 0; n < num_samples; ++n) {
    auto angle = ::sweep_scan_get_angle(releasing_scan.get(), n);
    auto distance = ::sweep_scan_get_distance(releasing_scan.get(), n);
    auto signal = ::sweep_scan_get_signal_strength(releasing_scan.get(), n);

    result.samples.push_back(sample{angle, distance, signal});
  }

  return result;
}

void sweep::reset() { ::sweep_device_reset(device.get(), detail::error_to_exception{}); }

} // ns

#endif

最佳答案

问题的简化版本:

buggy .hpp

int function() { return 0; }

主要.cpp

 #include "buggy.hpp"
 int main() { return 0; }

其他.cpp

 #include "buggy.hpp"

问题是 buggy.hpp定义 函数,而不仅仅是声明。一旦 header 包含被扩展,这意味着 functionmain.cppother.cpp 中声明 - 这是不允许的。

修复方法是将 function 声明为 inline,这允许在多个翻译单元中声明该函数。

inline int function() { return 0; }

事实上,允许多个定义是 唯一 inline 对 C++ 标准 的意义。编译器可能会将其视为可以内联扩展函数体的提示。好的不会;他们比程序员更擅长做出这类决定)。

关于c++ - 包括问题 : 'multiple definition' , 'first defined here',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45667393/

相关文章:

c++ - tellg() 函数 c++ 的奇怪行为

C++ 接口(interface)创建实例时出现问题

c++ - 推导 C++11 中 lambda 参数的类型

c++ - 如何访问具有多个括号的一维数组以提高可读性?

c++ - 有没有办法在 C++ 的类命名空间内定义某个类的全局常量?

c++ - 如何在 msvc 预处理器中打印宏?

c++ - const char* 没有被 C++ 正确解释为 Excel 库

c++ - 链表的构造函数

c++ - 时间优化 C++ 函数以找到解码可能性的数量

C++函数声明