14

I want to include implementation of a function inside an .h file.

I know I would rather separate declaration and implementation to .h and .c file accordingly, this is not a part of my question.

When I implement the function inside the class, I receive no errors:

class Foo
{
  public:
    // Class constructor
    Foo() { }
};

When I implement the function outside the class (still in the .h file):

class Foo
{
  public:
    // Class constructor
    Foo();
};

Foo::Foo()
{
}

I receive the following error: multiple definition of Foo:Foo()

Can someone explain me the logic behind this? Thanks.

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
Noa Yehezkel
  • 468
  • 2
  • 4
  • 20

2 Answers2

26

This is because when you define the function in the class definition, the method is treated as an inline function. Which can be included in multiple source files, be compiled and linked together and still have the linker not complain about multiple definitions.

But when you define the constructor outside the class, #include it in multiple source files, compile them together and then link them. You get multiple definitions for the same function.

Remember that #includeing a file is essentially a copy paste of that file into the file that #includes it. So every time that file is included, you get a definition for the function in that source file. And then when you compile and link multiple such sources together you get multiple definitions for the same non-inline function.


For more see on inline, see http://en.cppreference.com/w/cpp/language/inline. The examples section has a good chunk of code that should help.


You can also explicitly mark the definition outside the class to be inline like @StoryTeller correctly noted.

Curious
  • 20,870
  • 8
  • 61
  • 146
  • 1
    `inline` in C has different semantics to C++, I don't think that other question is relevant. The code in the linked question may fail to compile in C but is correct and good practice in C++ – M.M Jun 27 '17 at 08:12
  • @M.M updated my answer! Although just out of curiosity, what are the differences in semantics? – Curious Jun 27 '17 at 08:14
  • 1
    Have a look at https://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99 – M.M Jun 27 '17 at 08:17
15

Mark it inline

class Foo
{
  public:
    // Class constructor
    inline Foo();
};

inline Foo::Foo()
{
}

Like Curious said, an in-class definition is implicitly inline. But if you define it outside the class, in a header, you must add the specifier explicitly.

The inline specifier is very important for correct linkage in cases like this. It allows the same function to exist in multiple translation units, so long as it's the exact same function body. A case that often occurs with functions defined in a header file.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • What is inline required for in C++ then at all? wouldn't include guards be totally sufficient? – dhein Jun 27 '17 at 11:03
  • 1
    @dhein - Include guards protect you from double inclusion in the same translation unit. But headers are meant to be included freely in *separate* translation units. When the resulting object files are *linked*, you'd get an ODR violation, unless the compiler was informed it's an inline function. – StoryTeller - Unslander Monica Jun 27 '17 at 11:07
  • Oh, wait... I got it! Since which C++ this is included in the standard? I remember having encountered such a problem in a private project some years ago.... My teacher explained me to use prototypes for the functions to make my project work again. That helped for some time but just made the mess worse later on and I just dropped the project. I feel like digging it up again to see if this would have solved it back then. – dhein Jun 27 '17 at 11:15
  • 2
    @dhein - Since C++98. Originally also "a hint to the compiler" that the functions entire body should be inlined, but that is now deprecated. The linkage ramifications remain however, and are very important. – StoryTeller - Unslander Monica Jun 27 '17 at 11:19