头文件中定义的函数的重复符号

duplicate symbol of a function defined in a header file

假设我有一个头文件 file_ops.hpp 看起来像这样

#pragma once

bool systemIsLittleEndian() {
    uint16_t x = 0x0011;
    uint8_t *half_x = (uint8_t *) &x;
    if (*half_x == 0x11)
        return true;
    else
        return false;
}

我最初认为它与实现有关,但事实证明,我会得到重复的符号

#pragma once

bool systemIsLittleEndian() { return true; }

如果我做到了 inline,链接器错误就会消失。这不是我想要依赖的东西,因为 inline 是请求而不是保证。

是什么导致了这种行为?我没有处理返回某种单身人士的情况。

还有 个标记为

的其他方法
 bool MY_LIB_EXPORT someFunc();// implemented in `file_ops.cpp`

这些是否以某种方式相关(混合导出函数和 "plain old functions")?显然,我可以将实现移至 file_ops.cpp,我很想知道 为什么 会发生这种情况。

If I make it inline, the linker errors go away. That's not something I want to rely on, since inline is a request not a guarantee.

内联函数就可以了

即使未内联目标代码,语言也保证不会导致 linker 错误或未定义的行为,只要函数在不同的翻译单元中没有以某种方式改变。

如果您 #include 数百个 .cpp 文件中的 .hpp,您可能会注意到一些代码膨胀,但程序仍然正确。

What causes this behavior? I'm not dealing with a scenario where I'm returning some kind of singleton.

#include 机制有助于减少您必须在具有准确内容的多个文件中手动创建的代码量。最后,#include 其他文件的所有翻译单元都从它们 #include.

的文件中获取代码行

如果你 #include file_ops.hpp 在,比方说,file1.cpp 和 file2.cpp,就好像你有:

file1.cpp:

bool systemIsLittleEndian() {
    uint16_t x = 0x0011;
    uint8_t *half_x = (uint8_t *) &x;
    if (*half_x == 0x11)
        return true;
    else
        return false;
}

file2.cpp:

bool systemIsLittleEndian() {
    uint16_t x = 0x0011;
    uint8_t *half_x = (uint8_t *) &x;
    if (*half_x == 0x11)
        return true;
    else
        return false;
}

当您编译这两个 .cpp 文件并将它们 link 在一起以创建可执行文件时,linker 注意到名为 systemIsLittleEndian 的函数有两个定义。这就是 linker 错误的根源。

一个不使用inline

的解决方案

不使用 inline 解决您的问题的一个方法是:

  1. 在 .hpp 文件中声明函数。
  2. 在适当的 .cpp 文件中定义它..

file_ops.hpp:

bool systemIsLittleEndian(); // Just the declaration.

file_ops.cpp:

#include "file_ops.hpp"

// The definition.
bool systemIsLittleEndian() {
    uint16_t x = 0x0011;
    uint8_t *half_x = (uint8_t *) &x;
    if (*half_x == 0x11)
        return true;
    else
        return false;
}

更新

关于

 bool MY_LIB_EXPORT someFunc();// implemented in `file_ops.cpp`

网络上有很多相关信息。这是一个 Microsoft/Windows 问题。这里有几个了解它的起点。

  1. Exporting from a DLL Using __declspec(dllexport)
  2. Importing into an Application Using __declspec(dllimport)