I love the concept of DRY (don't repeat yourself [oops]), yet C++'s concept of header files goes against this rule of programming. Is there any drawback to defining a class member entirely in the header? If it's right to do for templates, why not for normal classes? I have some ideas for drawbacks and benefits, but what are yours?
-
Wouldn't that be DRY, and be the opposite of DIY? – ndim Nov 23 '09 at 15:34
-
9Actually, it's not the right thing to do for templates, but it is unfortunately the ONLY thing to do for templates. – Eric Nov 23 '09 at 15:41
-
See also [this related question](http://stackoverflow.com/q/1001639/96780) and, in particular, [my answer](http://stackoverflow.com/a/1001749/96780) quoting an article by Pedro Guerreiro. – Daniel Daranas Jul 12 '13 at 16:21
6 Answers
Possible advantages of putting everything in header files:
- Less redundancy (which leads to easier changes, easier refactoring, etc.)
- May give compiler/linker better opportunities for optimization
- Often easier to incorporate into an existing project
Possible disadvantages of putting everything in header files:
- Longer compile/link cycles
- Loss of separation of interface and implementation
- Could lead to hard-to-resolve circular dependencies
- Lots of inlining could increase executable size
- Prevents binary compatibility of shared libraries/DLLs
- Upsets co-workers who prefer the traditional ways of using C++

- 81,409
- 55
- 245
- 302
-
I don't think inlining applies in this case. The compiler should see the same source, just without the prototypes. I might be entirely wrong though. – Matt Nov 23 '09 at 15:53
-
2The inlining does apply. The compiler doesn't see the full function definitions in every translation unit, unless the definition is in a header. And that means it, in general, won't see the full definition when the function is called, which is where it'd be relevant to inline it. – jalf Nov 23 '09 at 16:24
Well - one problem is that typically implementations change much more often than class definitions - so for a large project you end up having to recompile the world for every small change.

- 9,123
- 5
- 40
- 38
-
2This is certainly a reason, but it's pretty low down on the list of reasons not to include the implementation in the header file. – Eric Nov 23 '09 at 15:44
-
3Everyone knows compilation times leads to lower productivity. I think this is a good reason not to. – Ben S Nov 23 '09 at 15:47
-
9@Eric - I'm currently working in the bowels of a million line piece of software that has a lot of class definitions in header files (for no good reason). Every time I change something I have to sit through a 5-10 minute recompile - it literally kills productivity. (But allows me to answer questions on StackOverflow!) – Aaron Nov 23 '09 at 16:05
-
4@Eric - depends on the project really. When I change a header file that is included by all compilation units it takes hours to recompile. If the code was in header files, no work would be possible any more. – Nemanja Trifunovic Nov 23 '09 at 16:36
-
With g++'s -j option for multicore compiling, I didn't see this is a problem. – May Oakes Nov 25 '09 at 19:33
-
1@Phineas - that just means you need a larger program to see the problem - not that the problem went away. You're still compiling more files than necessary - you're just compiling them faster. – Aaron Nov 25 '09 at 20:09
The main reason not to implement a class in the header file is: do the consumers of your class need to know its implementation details? The answer is almost always no. They just want to know what interface they can use to interact with the class. Having the class implementation visible in the header makes it much more difficult to understand what this interface is.
Beyond considerations of compactness and separating interface from implementation, there are also commercial motivations. If you develop a library to sell, you (probably) do not want to give away the implementation details of the library you are selling.

- 6,364
- 1
- 32
- 49
You're not repeating yourself. You only write the code once in one header. It is repeated by the preprocessor, but that's not your problem, and it's not a violation of DRY.
If it's right to do for templates, why not for normal classes
It's not really that it's the right thing to do for templates. It's just the only one that really works in general.
Anyway, if you implement a class in a header, you get the following advantages and disadvantages:
- The full implementation is visible anywhere it is used, which makes it easy for the compiler to inline as necessary.
- The same code will be parsed and compiled multiple times, leading to higher compile-times.
- On the other hand, if everything is in headers, that may lead to fewer translation units, and so the compiler has to run fewer times. Ultimately, you might end up with a single translation unit, which just includes everything once, which can result in very fast compilations.
And... that's it, really.
Most of my code tends to be in headers, but that's because most of my code is templates.

- 243,077
- 51
- 345
- 550
The main disadvantage (apart from the lengthy builds) is there is no clear separation of the interface and implementation.
Ideally, you should not need to see the implementation of an intuitive, and well documented interface.

- 1,789
- 15
- 23
-
Unfortunately, a C++ header file usually does contain a lot of implementation details, so it's not really that clean. (And before anyone else says it: Yeah, yeah, pimpl idiom, bla-bla-blah). – Kristopher Johnson Nov 24 '09 at 18:29
Not mentionned yet: virtual functions are instantiated for each include, so you can bloat your executable (I'm not sure whether this is true for all compilers).
There is an alternative:
Do a lot of stuff in classes declared in your source-file. 1 example is the pimpl-idiom, but there are also people who are afraid to declare classes out of the header-file. However, this makes sense for private classes.

- 14,072
- 2
- 31
- 53
-
Virtual functions? Did you mean template functions? They are not instantiated for each include, but for each type they're instantiated with. If 3 translation units instantiate `std::vector
`, for example, the linker will merge the 3 instantiations back into one. The bloat comes from instantiating with a large number of *different* types. – jalf Nov 23 '09 at 16:23 -
I meant virtual functions as in functions defined in the virtual table as mentionned in http://www.ddj.com/cpp/184403747, although there they say that it shouldn't be a real issue anymore, but it still depends on the good will of the compiler. – stefaanv Nov 23 '09 at 16:38