4

I usually only have the definitions of my classes inside a header if they are template classes.- If this is the case, i still like to split declaration and definition inside the header like that:

template<class T>
class Foo
{
public:

    Foo();

    void fooFunc();
};


template<class T>
Foo<T>::Foo()
{

}

template<class T>
void Foo<T>::fooFunc()
{

}

that code also compiles. But If I remove the template:

class Foo
{
public:

    Foo();

    void fooFunc();
};


Foo::Foo()
{

}

void Foo::fooFunc()
{

}

i get a duplicate symbol error for Foos functions. I was very sure that this should work and am very surprised that it does not. Is this expected behaviour? If I add an inline before the definition it works too.

Cœur
  • 37,241
  • 25
  • 195
  • 267
moka
  • 4,353
  • 2
  • 37
  • 63

2 Answers2

7

Yes, it's expected behavior.

Inline functions are meant to be compiled separately into each call site so duplication is no problem. For template functions, the compiler flags them in the object file such that the linker will basically ignore duplicates, since it can be difficult to predict where the template will or will not be instantiated.

But conventional functions are expected to be defined exactly once. If you define one in a header file, it gets compiled into each translation unit that includes the header, leading to a "duplicate symbol" error at link time if you have more than one object file containing a copy of the function.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • ok thank you, I usually never do this with non template classes and only stumbled upon this by accident.- I was very suprised that it didn't work but your explanation makes perfect sense! – moka Sep 28 '11 at 14:20
  • You may want to read about the [one-definition rule](http://en.wikipedia.org/wiki/One_Definition_Rule), and about "COMDAT sections", which are the mechanism used to merge duplicate definitions of template instantiations and out-of-line copies of inline functions. – Wyzard Sep 28 '11 at 14:25
0

I guess the linker knows the difference between a class that's defined in more than one translation unit and a templated class that's defined in more than one translation unit. For the former, it generates a duplicate symbol error, for the latter, it treats the two instances as the same thing and only uses one of them.

Skizz
  • 69,698
  • 10
  • 71
  • 108