12

I've seen that there are several different paradigms in C++ concerning what goes into the header file and what to the cpp file. AFAIK, most people, especially those from a C background, do:

foo.h

 class foo {
 private:
     int mem;
     int bar();
 public:
     foo();
     foo(const foo&);
     foo& operator=(foo);
     ~foo();
 }

foo.cpp

 #include foo.h
 foo::bar() { return mem; }
 foo::foo() { mem = 42; }
 foo::foo(const foo& f) { mem = f.mem; }
 foo::operator=(foo f) { mem = f.mem; }
 foo::~foo() {}
 int main(int argc, char *argv[]) { foo f; }

However, my lecturers usually teach C++ to beginners like this:

foo.h

 class foo {
 private:
     int mem;
     int bar() { return mem; }
 public:
     foo() { mem = 42; }
     foo(const foo& f) { mem = f.mem; }
     foo& operator=(foo f) { mem = f.mem; }
     ~foo() {}
 }

foo.cpp

 #include foo.h
 int main(int argc, char* argv[]) { foo f; }
 // other global helper functions, DLL exports, and whatnot

Originally coming from Java, I have also always stuck to this second way for several reasons, such as that I only have to change something in one place if the interface or method names change, that I like the different indentation of things in classes when I look at their implementation, and that I find names more readable as foo compared to foo::foo.

I want to collect pro's and con's for either way. Maybe there are even still other ways?

One disadvantage of my way is of course the need for occasional forward declarations.

2
  • 2
    foo.cpp now has nothing to do with your foo class and should be left empty (maybe but the #include to make your build system happy). Commented Feb 17, 2011 at 16:18
  • 2
    Your lecturers are insane. Commented Sep 12, 2015 at 15:18

4 Answers 4

16

While the second version is easier to write, it is mixing interface with implementation.

Source files which include header files need to be recompiled everytime the header files are changed. In the first version you'd change the header file only if you need to change the interface. In the second version you'd change the header file if you need to change the interface or the implementation.

Besides that you should not expose implementation details, you will get unneccessary recompilation with the second version.

2
  • 1
    +1 My profiler doesn’t instrument the code placed in header files - that's a valuable reason too.
    – Eugene
    Commented Feb 17, 2011 at 11:17
  • If you see my answer to this question programmers.stackexchange.com/questions/4573/… you will see how that depends a lot on the semantics of the class, i.e. what will be using it (in particular if it is an exposed part of your user interface and how many other classes in your system use it directly).
    – CashCow
    Commented Feb 17, 2011 at 14:00
3

I did it the second way back in '93-95. Took a few minutes to recompile a small app with 5-10 functions/files (on that same 486 PC .. and no, I didn't know about classes either, I was just 14-15 years old and there was no internet).

So, what you teach beginners and what you use professionally is vastly different techniques, especially in C++.

I think the comparison between C++ and a F1 car is apt. You don't put beginners in an F1 car (which doesn't even start unless you pre-heat the engine to 80-95 deg celcius).

Don't teach C++ as the first language. You should be experienced enough to know why option 2 is worse than option 1 in general, know a bit what static compilation/linking means and thus understand why C++ prefers it the first way.

1
  • This answer would be even better if you elaborated a little on static compilation/linking (I didn't know it back then!) Commented Jun 12, 2014 at 1:41
2

The second method is what I would call a totally-inlined class. You are writing a class definition but all your code using it will just inline the code.

Yes, the compiler decides when to inline and when not to... In this case you are helping the compiler make a decision though, and you will potentially end up actually generating less code and potentially faster.

This advantage is likely to outweigh the fact that if you modify the implementation of a function you need to rebuild all the source that uses it. In the lightweight nature of the class you will not be modifying the implementation. If you add a new method, you would have to modify the header anyway.

As your class gets more complex however, even adding a loop, the benefit of doing it this way goes down.

It does still have its advantages, in particular:

  • If this is "common-functionality" code you can just include the header and use it from multiple projects without having to link against a library that contains its source.

The downside of inlining becomes an issue when it means you have to bring in implementation specifics into your header, i.e. you have to start including extra headers.

Note that templates are a special case as you pretty much have to include the implementation detail. You might obscure it in another file but it needs to be there. (There is an exception to that rule with instantiations but in general you inline your templates).

1

It may not be significant, or true if your executable gets larger, but more code in header files allows the compiler more chances to optimize for speed.

If you're deciding whether to write a header-only library, this topic is just one of your concerns.

Not the answer you're looking for? Browse other questions tagged or ask your own question.