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

前端 未结 17 1781
终归单人心
终归单人心 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 15:59

    One disadvantage of your approach is you can't do parallel compilation. You might think you're getting a faster compile now, but if you have multiple .cpp files you can build them in parallel on either multiple core on your own machine or using a distributed build system like distcc or Incredibuild.

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

    I believe that unless you are using MSVC's pre-compiled headers, and you are using a Makefile or other dependency based build system, having separate source files should compile faster when building iteratively. Since, my development is almost always iterative, I care more about how fast it can recompile the changes I made in file x.cpp than in the twenty other source files that I didn't change. Additionally, I make changes much more frequently to the source files than I do to the APIs so they change less frequently.

    Regarding, circular dependencies. I would take paercebal's advice one step farther. He had two classes that had pointers to each other. Instead, I run into the case more frequently where one class requires another class. When this happens, I include the header file for the dependency in the header file of the other class. An example:

    // foo.hpp
    #ifndef __FOO_HPP__
    #define __FOO_HPP__
    
    struct foo
    {
       int data ;
    } ;
    
    #endif // __FOO_HPP__
    

    .

    // bar.hpp
    #ifndef __BAR_HPP__
    #define __BAR_HPP__
    
    #include "foo.hpp"
    
    struct bar
    {
       foo f ;
       void doSomethingWithFoo() ;
    } ;
    #endif // __BAR_HPP__
    

    .

    // bar.cpp
    #include "bar.hpp"
    
    void bar::doSomethingWithFoo()
    {
      // Initialize f
      f.data = 0;
      // etc.
    }
    

    The reason that I include this, which is slightly unrelated to circular dependencies, is that I feel there are alternatives to including header files willy-nilly. In this example the struct bar source file does not include the struct foo header file. This is done in the header file. This has an advantage in that a developer using bar does not have to know about any other files that the developer would need to include to use that header file.

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

    One thing nobody has brought up is that compiling large files requires a lot of memory. Compiling your whole project at once would require such a huge memory space that it just isn't feasible even if you could put all code in headers.

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

    You are right to say that your solution works. It may even have no cons for your current project and developing environment.

    But...

    As others stated, putting all your code in header files forces a full compilation every time you change one line of code. This may not be an issue yet but your project may grow large enough to the point compilation time will be an issue.

    Another problem is when sharing code. While you may not be directly concerned yet, it is important to keep as much code as possible hidden from a potential user of your code. By putting your code into the header file, any programmer using your code must look the whole code, while there are just interested in how to use it. Putting your code in the cpp file allows to only deliver a binary component (a static or dynamic library) and its interface as header files, which may be simpler in some environment.

    This is a problem if you want to be able to turn your current code into a dynamic library. Because you don't have a proper interface declaration decoupled from the actual code, you won't be able to deliver a compiled dynamic library and its usage interface as readable header files.

    You may not have these issues yet, that's why I was telling that your solution may be ok in your current environment. But it is always better to be prepared to any change and some of these issues should be addressed.

    PS: About C# or Java, you should keep in mind that these languages are not doing what you say. They are actually compiling files independently (like cpp files) and stores the interface globally for each file. These interfaces (and any other linked interfaces) are then used to link the whole project, that's why they are able to handle circular references. Because C++ does only one compilation pass per file, it is not able to globally store interfaces. That's why you are required to write them explicitely in header files.

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

    I like to think about separation of .h and .cpp files in terms of interfaces and implementations. The .h files contain the interface descriptions to one more classes and the .cpp files contain the implementations. Sometimes there are practical issues or clarity that prevent a completely clean separation, but that's where I start. For example, small accessor functions I typically code inline in the class declaration for clarity. Larger functions are coded in the .cpp file

    In any case, don't let compilation time dictate how you will structure your program. Better to have a program that's readable and maintainable over one that compiles in one 1.5 mintues instead of 2 minutes.

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

    The important philosophy of Object Oriented Programming lies in having data hiding leading to encapsulated classes with implementation hidden out from users. This is primarily to provide an abstraction layer where the users of a class primarily use the publicly accessible member functions for instance specific as well as static types. Then the developer of the class is free to modify the actual implementations provided the implementations are not exposed to the users. Even if the implementation is private and declared in a header file, changing the implementation will require all dependent codebase to re-compile. Whereas, if the implementation (definition of the member functions) are in a source code (non-header file), then the library gets changed, and the dependent codebase needs to re-link with the revised version of the library. If that library is dynamically linked one like a shared library then keeping the function signature (interface) same and implementation changed does not require re-linking also. Advantage? Of course.

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