Reputation: 2789
I had a function like this, that wasn't within a class:
// Gets the maximum number of tracks displayable
const utils::uint32 GetConstMaxSystemRange()
{
return constMaxSystemNumber - constMinSystemNumber + 1;
}
It compiled fine in VS2005, but then I got linker errors for each file after the first one to include it, even though I was using Compile Guards. On a hunch, I surrounded it with a class like so:
class CDSLimitsAccess
{
public:
// Gets the maximum number of tracks displayable
static const utils::uint32 GetConstMaxSystemRange()
{
return constMaxSystemNumber - constMinSystemNumber + 1;
}
protected:
CDSLimitsAccess(){}
};
And bang! Fixed.
Question: WHY?
Upvotes: 0
Views: 554
Reputation: 19374
Because if it is a free-floating function, on each include, it would be compiled into the .obj file, and when it comes to linking, there are duplicates.
For class members, there is a different policy, which allows for duplicates - which are later handled by the linker properly.
You can put it into a unnamed namespace, or add a static before it, so it will become local to the translation unit. However, this is not the right way to fix it - just include the declaration in the header, and put the implementation into a file, and you'll be fine.
Upvotes: 3
Reputation: 506837
Include guards only protect that function from being included into the same translation unit twice. But it won't protect that function from being included into the whole program twice.
As the function is non-inline, it violates the One Definition Rule if it appears more than once in the whole program. Make it inline to solve the problem, or put the definition into a implementation file, putting only its declaration in the header.
// Gets the maximum number of tracks displayable. possible fix:
inline utils::uint32 GetConstMaxSystemRange() {
return constMaxSystemNumber - constMinSystemNumber + 1;
}
On a side note - better don't put const on a built-in return value. Temporaries of them can't be qualified with const / volatile. But that's also not necassary: You can't modify them anyway. It's ignored as far as i know. But it won't ever have an effect.
Upvotes: 13