假设我有一个头文件 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
的解决方案是:
- 在 .hpp 文件中声明函数。
- 在适当的 .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 问题。这里有几个了解它的起点。
关于c++11 - 头文件中定义的函数的重复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47945654/