0

我有一个这样的函数,它不在一个类中:

// Gets the maximum number of tracks displayable
const utils::uint32 GetConstMaxSystemRange()
{
    return constMaxSystemNumber - constMinSystemNumber + 1;
}

它在 VS2005 中编译得很好,但是在第一个包含它的文件之后,我得到了每个文件的链接器错误,即使我使用的是 Compile Guards。凭直觉,我用这样的课程包围了它:

class CDSLimitsAccess
{
public:
    // Gets the maximum number of tracks displayable
    static const utils::uint32 GetConstMaxSystemRange()
    {
        return constMaxSystemNumber - constMinSystemNumber + 1;
    }

protected:
    CDSLimitsAccess(){}
};

砰!固定的。

问题:为什么?

4

2 回答 2

13

包含守卫仅保护该函数不被包含到同一个翻译单元中两次。但它不会保护该函数不被两次包含到整个程序中。

由于该函数是非内联的,如果它在整个程序中出现不止一次,它就违反了单一定义规则。使其内联以解决问题,或将定义放入实现文件中,仅将其声明放在标题中。

// Gets the maximum number of tracks displayable. possible fix:
inline utils::uint32 GetConstMaxSystemRange() {
    return constMaxSystemNumber - constMinSystemNumber + 1;
}

附带说明 - 最好不要将 const 放在内置返回值上。它们的临时变量不能用 const / volatile 限定。但这也不是必需的:无论如何您都不能修改它们。据我所知,它被忽略了。但它永远不会有效果。

于 2009-01-12T11:34:18.033 回答
3

因为如果它是一个自由浮动函数,在每个包含时,它都会被编译成 .obj 文件,并且在链接时,会有重复。

对于类成员,有一个不同的策略,它允许重复 - 稍后由链接器正确处理。

你可以把它放到一个未命名的命名空间中,或者在它之前添加一个静态,这样它就会成为翻译单元的本地。但是,这不是修复它的正确方法 - 只需在标头中包含声明,然后将实现放入文件中,就可以了。

于 2009-01-12T11:36:39.603 回答