17

I aware of three different kind of implementation "locations" for my class methods:

1) Define the method inside my class (.h file) and implement it in my .cpp file

//.h
class Foo
{
  int getVal() const;
};


//.cpp
int Foo::getVal() const
{ return 0; }

2) Define and implement the method inside my class (.h file).

//.h
class Foo
{
  int getVal() const
  { return 0; }
};

3) Define the method inside my class and implement it outside the class but inside my header file.

//.h
class Foo
{
  int getVal() const;
};

int Foo::getVal() const
{ return 0; }

What are the main differences between these three approaches?

Nick
  • 10,309
  • 21
  • 97
  • 201
  • 4
    #3 is likely to lead to a linker error (as soon as you include this header into more than one source file). – Igor Tandetnik Feb 02 '15 at 17:46
  • 1
    #2 will let the compiler inline the function where applicable (without requiring whole-program optimization), so it's generally used for small getter/setter functions like you've shown in your example. For templated classes (only), #1 is not an option, and #2 and #3 become equivalent. – Cameron Feb 02 '15 at 17:47
  • For faster compile speeds, prefer #1 as much as possible. – Neil Kirk Feb 02 '15 at 17:51
  • Related questions: [here](http://stackoverflow.com/q/5057021/509868) and [here](http://stackoverflow.com/q/495021/509868) – anatolyg Feb 02 '15 at 17:53
  • Note that where you are saying "define," the proper term is declare. A function's definition includes the body of the function. – Jon Kalb Feb 02 '15 at 22:40

3 Answers3

14

There are three elements to this question: readability (how good the code looks), compilation (how much the compiler can optimize it) and implementation hiding (If you use the code as a library, you may not want to explicitly share your special sauce with the world).

Method one exposes only the interface for the function in the header file. This means you show a nice clean interface, and your implementation is not exposed in plaintext. However, the code cannot be inlined across compilation units, so it has the potential to be a little slower in runtime (in practice, this only matters for a very, very very small percentage of the code). THIS SHOULD BE YOUR DEFAULT WAY TO GO.

Method 2 is implicit inlining. Long functions will clutter up your class which (imho) is bad. Also exposes your implementation to the world. However, the function can be inlined and is less verbose than defining it in another place. I reserve this for very small functions.

Method 3 is actually illegal, as you will break the one-definition rule, but the following is fine:

//Foo.h
class Foo {
  int getVal() const;
};

inline int Foo::getVal() const { 
  return 0; 
}

I use this when I want to keep the class definition clean but want the function definition in the header file (for inlinable or template functions).

IdeaHat
  • 7,641
  • 1
  • 22
  • 53
2

(1) will compile faster for a large project (only have to compile the definition of getVal once in Foo.cpp, and only have to recompile one thing if definition changes), and you get a very clear interface for a class for people who want to look it up. On the other hand, you can't inline getVal().

(2) and (3) will compile slower and add way more dependencies to your definitions changing. But you can inline getVal(). Also this is required if getVal is a template function. NOTE (3) will cause linker errors if your header is included multiple times - you'll have to mark remember to label your function inline. This is a good reason to prefer (1) and (2) to (3).

Really it's not a matter of picking (1) vs (2). You will probably use both in large projects - put the definitions of the functions that should be inlined (and templates) in the header, and put the ones that inlining makes less sense for in the cpp.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 2
    This answer is incomplete. It only describes compilation speed, which is not the only concern, and probably not the most important one. – anatolyg Feb 02 '15 at 17:54
  • @anatolyg For my project that takes minutes to build, it's the most important concern. – Neil Kirk Feb 02 '15 at 17:58
  • The only thing missing from the answer is the possible ODR issue if header is included multiple times with 3); Disagree with comment from @anatolyg and have upvoded – Stefan Atev Feb 02 '15 at 17:58
  • 1
    @anatolyg The answer does not "only" describe compilation speed. The which is the "most important" concern is purely a matter of opinion and a function of what the project in question actually is. – Barry Feb 02 '15 at 18:07
1

A minor note before I begin, there are lots of words that are very similar used to describe these things, I will be using declaration for the portion in the header file (int getVal() const) and implementation for the portion in the cpp file (int Foo::getVal() const). Apologies if these aren't perfectly accurate.

Also note that benefits are penalties for the others, in case that isn't clear.

1) Define the method inside my class (.h file) and implement it in my .cpp file

This is considered the standard method, and generally accepted to be the default (there are numerous exceptions, so default might be a little strong).

It separates the declaration from the implementation. This provides a few benefits:

  • You only need to compile the implementation once. This could potentially save compilation time.
  • You only need the declaration to reference. This can avoid ordering issues and is vital for circular references between classes.
  • You don't distribute your implementation, this can be good for closed source systems as you often have to distrbute lots of your .h files for others to plug into your system.

2) Define and implement the method inside my class (.h file).

This is called an inline implementation, it should be used in simple implementations only. It has a few benefits too:

  • Most compilers take this as a huge inline hint. It doesn't guarantee inling but it is very likely, which for simple methods can be a win. Property style methods are a common example.
  • Your implementation is trivial to find as it is straight in the declaration.

3) Define the method inside my class and implement it outside the class but inside my header file.

I haven't seen this before, but would assume it is used when the definition is non-trivial but you want the inline benefits of 2. IdeaHat mentions that the inline keyword is required in this case.

Community
  • 1
  • 1
Guvante
  • 18,775
  • 1
  • 33
  • 64
  • 1
    #3 is common for complex templates. You have a relatively normal looking class definition, and then the complex function definitions come after. The inline keyword is not required in the `template` case. – Mooing Duck Feb 02 '15 at 20:17