Clean up your #include statements?

后端 未结 12 1303
梦如初夏
梦如初夏 2020-12-05 13:18

How do you maintain the #include statements in your C or C++ project? It seems almost inevitable that eventually the set of include statements in a file is either insufficie

相关标签:
12条回答
  • 2020-12-05 13:49

    If you use Visual Studio compiler, you can try /showIncludes compiler option and then parse what it emits to stderr. MSDN: "Causes the compiler to output a list of the include files. Nested include files are also displayed (files that are included from the files that you include)."

    0 讨论(0)
  • 2020-12-05 13:49

    If you are coding in Eclipse with CDT, you can use Organize Includes command. Just hit Ctrl+Shift+O and it will add the necessary includes and remove the unneeded ones.

    0 讨论(0)
  • 2020-12-05 13:55

    Take a look at the cppclean project. Though they haven't implemented that feature yet, but it's planned to be done.

    From the project site:

    CppClean attempts to find problems in C++ source that slow development particularly in large code bases. It is similar to lint; however, CppClean focuses on finding global inter-module problems rather than local problems similar to other static analysis tools.

    The goal is to find problems that slow development in large code bases that are modified over time leaving unused code. This code can come in many forms from unused functions, methods, data members, types, etc to unnecessary #include directives. Unnecessary #includes can cause considerable extra compiles increasing the edit-compile-run cycle.

    And particularly on the #include feature:

    • (planned) Find unnecessary header files #included
      • No direct reference to anything in the header
      • Header is unnecessary if classes were forward declared instead
    • (planned) Source files that reference headers not directly #included, ie, files that rely on a transitive #include from another header

    Here you can find a mirror at BitBucket.

    0 讨论(0)
  • 2020-12-05 13:57

    To verify that header files are including everything they need, I would creating a source file that all it does is include a header file and try to compile it. If the compile fails, then the header file itself is missing an include.

    You get the same effect by making the following rule: that the first header file which foo.c or foo.cpp must include should be the correspondingly-named foo.h. Doing this ensures that foo.h includes whatever it needs to compile.

    Furthermore, Lakos' book Large-Scale C++ Software Design (for example) lists many, many techniques for moving implementation details out of a header and into the corresponding CPP file. If you take that to its extreme, using techniques like Cheshire Cat (which hides all implementation details) and Factory (which hides the existence of subclasses) then many headers would be able to stand alone without including other headers, and instead make do with just forward declaration to opaque types instead ... except perhaps for template classes.

    In the end, each header file might need to include:

    • No header files for types which are data members (instead, data members are defined/hidden in the CPP file using the "cheshire cat" a.k.a. "pimpl" technique)

    • No header files for types which are parameters to or return types from methods (instead, these are predefined types like int; or, if they're user-defined types, then they're references in which case a forward-declared, opaque type declaration like merely class Foo; instead of #include "foo.h" in the header file is sufficient).

    What you need then is the header file for:

    • The superclass, if this is a subclass

    • Possibly any templated types which are used as method parameters and/or return types: apparently you're supposed to be able to forward-declare template classes too, but some compiler implementations may have a problem with that (though you could also encapsulate any templates e.g. List<X> as implementation details of a user-defined type e.g. ListX).

    In practice, I might make a "standard.h" which includes all the system files (e.g. STL headers, O/S-specific types and/or any #defines, etc) that are used by any/all header files in the project, and include that as the first header in every application header file (and tell the compiler to treat this "standard.h" as the 'precompiled header file').


    //contents of foo.h
    #ifndef INC_FOO_H //or #pragma once
    #define INC_FOO_H
    
    #include "standard.h"
    class Foo
    {
    public: //methods
      ... Foo-specific methods here ...
    private: //data
      struct Impl;
      Impl* m_impl;
    };
    #endif//INC_FOO_H
    

    //contents of foo.cpp
    #include "foo.h"
    #include "bar.h"
    Foo::Foo()
    {
      m_impl = new Impl();
    }
    struct Foo::Impl
    {
      Bar m_bar;
      ... etc ...
    };
    ... etc ...
    
    0 讨论(0)
  • 2020-12-05 14:00

    Depending on the size of your project, looking at the include graphs created by doxygen (with the INCLUDE_GRAPH option on ) can be helpful.

    0 讨论(0)
  • 2020-12-05 14:03

    Yup. We have a preprocessor of our own which gives us access to our own macro language. It also checks that header files are only included one time. Creating a simple preprocessor checking for multiple includes should be fairly easy.

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