views:

145

answers:

3

While I was reading the accepted answer of this question, I had the following question:

Typically, methods are defined in header files (.hpp or whatever), and implementation in source files (.cpp or whatever).

One of the main reasons it is bad practice to ever include a "source file" (#include <source_file.cpp>) is that its methods implementation would then be duplicated, resulting in linking errors.

When one writes:

#ifndef BRITNEYSPEARS_HPP
#define BRITNEYSPEARS_HPP

class BritneySpears
{
  public:

    BritneySpears() {}; // Here the constructor has implementation.
};

#endif /* BRITNEYSPEARS_HPP */

He is giving the implementation of the constructor (here an "empty" implementation, but still).

But why then including this header file multiple times (aka. on different source files) will not generate a "duplicate definition" error at link time ?

+2  A: 

Because it is an "inline" function. Inline functions can be included from headers as many times as you like and they don't cause duplicate definition linker errors.

The compiler will also try to bring them inline so, in your example above, the compiler will try and eliminate the call to the constructor completely.

Goz
+11  A: 

Functions with "inline linkage" are exceptions to the "one definition rule": you are allowed to have identical implementations of them in more than one compilation unit. Functions have inline linkage if they are declared inline or implemented inside a class definition.

Mike Seymour
Are you sure about this? If I compile this and look at the disassembly, I clearly see a "call" instruction. So, no inlining. Also, I can declare recursive functions in the class definition, include them multiple .cpp files and get no linker error. How can they be inlined? (Might be MS-specific behavior, though)
nikie
@nikie: Even though there might be a call instruction there, the functions are treated differently by the linker, see the link in my answer for details.
sharptooth
@nikie "inline function" doesn't mean calls to it are inlined. It just means they get special treatment by the linker so multiple definitions of them are allowed in the program. For calls to be inlined this is necessary - because only then, multiple TUs can see the code and not only one TU. But it's not sufficient - the compiler can still use plain call instructions.
Johannes Schaub - litb
@nikie The compiler is never required to physically inline anything. -
anon
@all: my mistake. I thought "inline function" meant that calls to the function had to be inlined. Thanks for the clarification.
nikie
I have to say I use the `inline` keyword more frequently for its linker properties than for performance!
AshleysBrain
Thank you very much for the precise explanation ;)
ereOn
+7  A: 

Member functions with implementation inside the class definition are treated as inline functions. Inline functions are exempt from one definition rule.

Specifically when the linker sees two inline functions with the same signature it treats them as if it is the same function and just picks one of them. This can lead to really weird hard to detect problems.

sharptooth