Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

architecture - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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:

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...