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

前端 未结 17 1780
终归单人心
终归单人心 2020-12-02 15:48

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

相关标签:
17条回答
  • 2020-12-02 16:09

    You might want to check out Lazy C++. It allows you to place everything in a single file and then it runs prior to compilation and splits the code into .h and .cpp files. This might offer you the best of both worlds.

    Slow compile times are usually due to excessive coupling within a system written in C++. Maybe you need to split code into subsystems with external interfaces. These modules could be compiled in separate projects. This way you can minimize the dependency between different modules of the system.

    0 讨论(0)
  • 2020-12-02 16:10

    You're going outside of the design scope of the language. While you may have some benefits, it's going to eventually bite you in the butt.

    C++ is designed for h files having declarations, and cpp files having implementations. Compilers are built around this design.

    Yes, people debate whether that's a good architecture, but it's the design. It's better to spend your time on your problem than reinventing new ways to design C++ file architecture.

    0 讨论(0)
  • 2020-12-02 16:11

    The obvious downside to me is that you always have to build all the code at once. With .cpp files, you can have separate compilation, so you're only rebuilding bits that have really changed.

    0 讨论(0)
  • 2020-12-02 16:11

    One thing you're giving up that I would have a hard time living without is anonymous-namespaces.

    I find that they're incredibly valuable for defining class-specific utility functions that should invisible outside the class's implementation file. They're also great for holding any global data that should be invisible to the rest of the system,like a singleton instance.

    0 讨论(0)
  • 2020-12-02 16:14

    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.

    0 讨论(0)
提交回复
热议问题