海湾合作委员会多重定义..仅释放
gcc Multiple definition...release only
我在头文件中定义了一个函数。在调试中,它可以很好地编译和链接。在发布中,对于包含标头的每个类的每个对象文件,我收到编译错误"'blah::blah(blah&blah)'的多个定义"。
我正在使用 gcc-4.8.1。我无法发布实际代码,此版本已更改名称以保护无辜者:
#ifndef INCLUDE_SMELLS_FUNNY
#define INCLUDE_SMELLS_FUNNY
#include "ParentClass.h"
#include "ChildClassA.h"
#include "ChildClassB.h"
namespace someplace {
bool smellsFunny(const ParentClass& someData) {
// All ChildClass As smell funny
if(dynamic_cast<const ChildClassA*>(&someData)) {
return true;
}
// If ChildClass B, need to check if smells funny
const ChildClassB* childB = dynamic_cast<const ChildClassB*>(&someData)
if(childB) {
return childB->MoreThanAWeekOld();
}
// Default is smells OK
return false;
}
}
#endif // INCLUDE_SMELLS_FUNNY
我无法找到哪个 gcc 标志负责。当然,修复只是将实现移动到 cpp 文件中。但为什么这是必要的呢?为什么这只发生在发布中?
这是因为
您在头文件中定义了函数,然后将该头文件包含在多个源文件中。这意味着该函数将在包含标头的每个源文件(技术上是翻译单元)中定义。
对此有几种解决方案:
- 将函数标记为
static
。这意味着不会导出翻译单元中的每个定义。 - 将函数标记为
inline
。这与第一种选择基本相同。 - 将函数的定义放在源文件中,并且仅在头文件中具有其声明。
对于像您这样的小函数,则备选方案 2 可能是一个不错的函数。如果你有一个更大的函数,不容易内联,你应该使用备选方案3。
此外,如果使用数字 3,则无需包含头文件,然后降低循环包含的风险。
由于您已将函数定义放在标头中,因此需要将其标记为inline
:
inline bool smellsFunny(const ParentClass& someData) { ...
这是因为包含标头的每个位置都将具有函数的定义,从而打破了一个定义规则 (ODR)。 inline
允许您绕过 ODR。
至于为什么在发布模式下没有问题,这是没有意义的:代码不正确。可能是发布模式正在为您内联声明函数。
我不能确切地说,但也许在调试模式下,该函数被视为内联函数。
如果函数在头文件中,则需要将其声明inline
,除非它是在类中定义的。
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 释放错误后堆使用
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 引用释放的内存是未定义的行为吗?
- C++ 释放自定义类向量的正确方法
- 如何在SWIG中释放自定义构造函数中分配的内存
- 分配给 cpp 中定义的全局静态变量的内存是否在 C++ 中删除其类的实例后释放
- 释放用户定义表达式析构函数中的动态内存
- 海湾合作委员会多重定义..仅释放
- 释放自定义堆栈分配器中的内存
- 自定义队列中C++错误:未分配正在释放的指针
- 在函数中定义一个动态数组,然后返回数组元素。如何释放阵列的内存?
- 为什么释放无效指针在c++中没有定义
- 在用户定义的类中清空 std::vector 时不释放内存