Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pros & Cons of putting all code in Header files in C++?

You can structure a C++ program so that (almost) all the code resides in Header files. It essentially looks like a C# or Java program. However, you do need at least one .cpp file to pull in all the header files when compiling. Now I know some people would absolutely detest this idea. But I haven't found any convincing downsides of doing this. I can list some advantages:

[1] Faster compile times. All header files only get parsed once, because there is only one .cpp file. Also, one header file cannot be included more than once, otherwise you will get a build break. There are other ways of achieving faster compiles when using the alternate approach, but this is so simple.

[2] It avoids circular dependencies, by making them absolutely clear. If ClassA in ClassA.h has a circular dependency on ClassB in ClassB.h, I have to put a forward reference & it sticks out. (Note that this is unlike C# & Java where the compiler automatically resolves circular dependencies. This encourages bad coding practices IMO). Again, you can avoid circular dependencies if your code was in .cpp files, but in a real-world project, .cpp files tend to include random headers until you can't figure out who depends on whom.

Your thoughts?

like image 819
user15071 Avatar asked Oct 11 '08 08:10

user15071


People also ask

What pros mean?

adverb. in favor of a proposition, opinion, etc. noun, plural pros. a proponent of an issue; a person who upholds the affirmative in a debate. an argument, consideration, vote, etc., for something.

What is mean by pros and cons?

pros and cons. Arguments or considerations for and against something, as in We'd best weigh all the pros and cons before we decide to add a new wing to the library. This idiom is taken from the Latin pro for “for” and con for “against.” [ Late 1500s]

What is the full word for pros and cons?

The phrase 'pros and cons' is an abbreviation of the Latin phrase pro et contra, 'for and against', and has been in use in the abbreviated form since the 16th century, according to the Oxford English Dictionary.

Is a pro a good thing?

“Pro” generally demonstrates a favorable opinion, although as a prefix, it can also represent prior occurrences. We often use “pro” in the context of “pros and cons.” The opposite of “pro” is “con” or “anti,” meaning that you feel negative about an idea or do not support the argument (source).


2 Answers

Reason [1] Faster compile times

Not in my projects: source files (CPP) only include the headers (HPP) they need. So when I need to recompile only one CPP because of a tiny change, I have ten times the same number of files that are not recompiled.

Perhaps you should break down your project in more logical sources/headers: A modification in class A's implementation should NOT need the recompilation of implementations of class B, C, D, E, etc..

Reason[2] It avoids circular dependencies

Circular dependencies in code?

Sorry, but I have yet to have this kind of problem being a real problem: Let's say A depends on B, and B depends on A:

struct A {    B * b ;    void doSomethingWithB() ; } ;  struct B {    A * a ;    void doSomethingWithA() ; } ;  void A::doSomethingWithB() { /* etc. */ } void B::doSomethingWithA() { /* etc. */ } 

A good way to resolve the problem would be to break down this source into at least one source/header per class (in a way similar to the Java way, but with one source and one header per class):

// A.hpp  struct B ;  struct A {    B * b ;    void doSomethingWithB() ; } ; 

.

// B.hpp  struct A ;  struct B {    A * a ;    void doSomethingWithA() ; } ; 

.

// A.cpp #include "A.hpp" #include "B.hpp"  void A::doSomethingWithB() { /* etc. */ } 

.

// B.cpp #include "B.hpp" #include "A.hpp"  void B::doSomethingWithA() { /* etc. */ } 

Thus, no dependency problem, and still fast compile times.

Did I miss something?

When working on "real-world" projects

in a real-world project, cpp files tend to include random headers until you can't figure out who depends on whom

Of course. But then if you have time to reorganize those files to build your "one CPP" solution, then you have time to clean those headers. My rules for headers are:

  • break down header to make them as modular as possible
  • Never include headers you don't need
  • If you need a symbol, forward-declare it
  • only if the above failed, include the header

Anyway, all headers must be self-sufficient, which means:

  • An header include all needed headers (and only needed headers - see above)
  • an empty CPP file including one header must compile without needing to include anything else

This will remove ordering problems and circular dependencies.

Is compile times an issue? Then...

Should compile time be really an issue, I would consider either:

  • Using precompiled headers (this is quite useful for STL and BOOST)
  • Decrease coupling through the PImpl idiom, as explained in http://en.wikipedia.org/wiki/Opaque_pointer
  • Use network shared compilation

Conclusion

What you are doing is not putting everything in headers.

You are basically including all your files into one and only one final source.

Perhaps you are winning in terms of full-project compilation.

But when compiling for one small change, you'll always lose.

When coding, I know I compile often small changes (if only to have the compiler validate my code), and then one final time, do a full project change.

I would lose a lot of time if my project was organized your way.

like image 180
paercebal Avatar answered Sep 21 '22 12:09

paercebal


I disagree with point 1.

Yes, there is only one .cpp and the built time from scratch is faster. But, you rarely build from scratch. You make small changes, and it would need to recompile the whole project each time.

I prefer doing it the other way around:

  • keep shared declarations in .h files
  • keep definition for classes that are only used in one place in .cpp files

So, some of my .cpp files start looking like Java or C# code ;)

But, 'keeping stuff in .h' approach is good while designing the system, because of point 2. you made. I usually do that while I'm building the class hierarchy and later when code architecture becomes stable, I move code to .cpp files.

like image 21
Milan Babuškov Avatar answered Sep 18 '22 12:09

Milan Babuškov