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

sve*_*evs 4 header-files c++11

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;
}
Run Code Online (Sandbox Code Playgroud)

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

#pragma once

bool systemIsLittleEndian() { return true; }
Run Code Online (Sandbox Code Playgroud)

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

是什么导致了这种行为?我不是在处理返回某种单例的情况。

还有其他方法被标记为

 bool MY_LIB_EXPORT someFunc();// implemented in `file_ops.cpp`
Run Code Online (Sandbox Code Playgroud)

这些是否以某种方式相关(混合导出函数和“普通旧函数”)?显然我可以将实现移至file_ops.cpp,我对为什么会发生这种情况很感兴趣。

R S*_*ahu 8

如果我将其内联,链接器错误就会消失。这不是我想要依赖的东西,因为内联是一个请求而不是保证。

内联函数就可以了。

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

如果您将#include.hpp 包含在数百个 .cpp 文件中,您可能会注意到代码有点膨胀,但程序仍然是正确的。

是什么导致了这种行为?我不是在处理返回某种单例的情况。

#include机制可以方便地减少您必须在具有确切内容的多个文件中手动创建的代码量。最后,#include其他文件的所有翻译单元都从它们的文件中获取代码行#include

如果您将#includefile_ops.hpp 放入 file1.cpp 和 file2.cpp 中,就好像您有:

文件1.cpp:

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

文件2.cpp:

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

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

一种解决方案,无需使用inline

不使用 来解决您的问题的一种解决方案inline是:

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

文件操作.hpp:

bool systemIsLittleEndian(); // Just the declaration.
Run Code Online (Sandbox Code Playgroud)

文件操作.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;
}
Run Code Online (Sandbox Code Playgroud)

更新

关于

 bool MY_LIB_EXPORT someFunc();// implemented in `file_ops.cpp`
Run Code Online (Sandbox Code Playgroud)

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

  1. 使用 __declspec(dllexport) 从 DLL 导出
  2. 使用 __declspec(dllimport) 导入到应用程序中

  • 实际上还有第二种解决方案:将头文件中的函数定义标记为静态。这样,它就成为包含头文件的每个翻译单元(即 cpp 文件)的本地文件,从而消除了重复。 (3认同)