c++11 - 头文件中定义的函数的重复符号

标签 c++11 header-files

假设我有一个头文件 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 是请求而不是保证。

是什么导致了这种行为?我不会处理返回某种单例的场景。

还有其他标记为

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

这些是否以某种方式相关(混合导出函数和“普通旧函数”)?显然,我可以将实现移至 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.

内联函数就OK了。

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

如果您在数百个 .cpp 文件中#include .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,就好像您有:

文件1.cpp:

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

文件2.cpp:

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

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

一种不使用inline的解决方案

不使用 inline 的解决方案是:

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

文件_ops.hpp:

bool systemIsLittleEndian(); // Just the declaration.

文件_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)

关于c++11 - 头文件中定义的函数的重复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47945654/

相关文章:

c++ - 在 C++ 中包含两次头文件

c - 在 .c 文件中声明和定义的函数

c++ - include files, typedefs 和 forward decl

我的类中的 c++ condition_variable wait_for 谓词,std::thread <unresolved overloaded function type> error

c++ - 比较键和值 std::maps

C++11, `noexcept` 说明符,定义与声明

c++ - header 包含的嵌套深度是否有限制?

c++ - 为什么将 T 从外部模板作为默认参数传递给 std::function 会导致编译错误?

c++ - VS2015错误C2976

c++ - 类中的动态数组和指针很难找到定义它们的正确方法