我在头文件中定义了一个函数。在调试中,它编译并链接良好。在发行版中,对于包含头的每个类的每个对象文件,我都会得到编译错误“‘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文件中。但为什么有这个必要呢?为什么只有在发布时才会发生这种情况?
发布于 2013-11-05 09:09:14
我不能确切地说,但是在调试模式下,函数被认为是内联函数。
发布于 2013-11-05 09:08:37
由于您已经将函数定义放置在标头中,所以需要将其标记为inline。
inline bool smellsFunny(const ParentClass& someData) { ...这是因为包含标头的每个地方都有函数的定义,从而打破了“一个定义规则”(ODR)。inline允许您绕过ODR。
至于为什么在发布模式中没有问题,这是没有意义的:代码是不正确的。可能是发布模式是为您内联声明函数。
发布于 2013-11-05 09:08:49
这是因为您在头文件中定义了函数,然后将该头文件包含在多个源文件中。这意味着函数将定义在每个源文件中(从技术上讲,翻译单元),其中包含标头。
对此有几种解决方案:
static。这意味着翻译单位中的每个定义都不会被导出。inline。这基本上和第一种选择是一样的。对于一个像你这样的小函数来说,备选方案2可能是个好函数。如果您有一个更大的函数,这是很难内联的,您应该使用备选方案3。
另外,如果使用数字3,则不需要包含头文件,然后减少循环包含的风险。
https://stackoverflow.com/questions/19785173
复制相似问题