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

时间:2017-12-22 18:10:30

标签: 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,链接器错误就会消失。这不是我想要依赖的东西,因为inline是一个请求而不是保证。

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

其他标记为

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

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

1 个答案:

答案 0 :(得分:4)

  

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

可以内联函数。

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

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

  

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

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

如果您{file = .c}和file2.cpp中有#include file_ops.hpp,那就好像您有:

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文件并将它们链接在一起以创建可执行文件时,链接器会注意到有两个名为systemIsLittleEndian的函数的定义。这是链接器错误的来源。

不使用inline

的一种解决方案

在不使用inline的情况下,您的问题的一个解决方案是:

  1. 在.hpp文件中声明该函数。
  2. 在相应的.cpp文件中定义..
  3. 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)