这是一个相当基本的问题,但它是一个让我误解了一段时间的问题.
我的项目有一堆.cpp(实现)和.hpp(定义)文件.
我发现当我添加其他类和更多类的相互依赖时,我必须#include其他头文件.一两个星期之后,我最终在很多地方使用了#include指令.稍后,我会尝试删除一些#includes并发现一切仍然有效,因为其他包含的类也包括#include我刚删除的内容.
是否有一个简单,容易的规则来放入#includes,这将阻止这个丑陋的混乱发生在一开始?什么是最佳做法?
例如,我参与了一个项目,其中Implementation .cpp文件只包含相应的Definition .hpp文件,而没有其他任何内容.如果Implementation .cpp需要使用任何其他.hpp文件,则它们都由Definition .hpp文件引用.
一些最佳实践:
每个.cpp或.C文件都包含它需要的所有标头,并且不依赖于包括其他相关标头的标头
每个.hpp或.h文件都包含其所有依赖项,并且不依赖于包含其他相关标头的包含标头
每个标题都包含:
#ifndef HEADER_XXX_INCLUDED #define HEADER_XXX_INCLUDED ... #endif /* HEADER_XXX_INCLUDED */
标题不包括周期中的其他标题
常:有一个单一的"项目范围头文件"喜欢"的config.h"或".H",它总是包含首先通过任何的.cpp或者.C文件.通常,这具有与平台相关的配置数据,项目范围的常量和宏等.
这些不一定是"最佳实践",但我通常遵循的规则也是:
特定于项目的标头包含#include "..."
在系统范围的标头之前和之前,包括在内#include <...>
特定于项目的标题按字母顺序包含,作为确保不包含它们的顺序的偶然隐藏要求的方法.由于每个标题应包含其依赖项,并且标题应受到保护以防止多次包含,因此您应该能够按照您希望的任何顺序包含它们.
查看John Lakos的大规模C++软件设计.这就是我所遵循的(作为例子写的):
// foo.h // 1) standard include guards. DO NOT prefix with underscores. #ifndef PROJECT_FOO_H #define PROJECT_FOO_H // 2) include all dependencies necessary for compilation #include// 3) prefer forward declaration to #include class Bar; class Baz; #include // this STL way to forward-declare istream, ostream class Foo { ... }; #endif
// foo.cxx // 1) precompiled header, if your build environment supports it #include "stdafx.h" // 2) always include your own header file first #include "foo.h" // 3) include other project-local dependencies #include "bar.h" #include "baz.h" // 4) include third-party dependencies #include#include #include #include
// stdafx.h // 1) make this easy to disable, for testing #ifdef USE_PCH // 2) include all third-party dendencies. Do not reference any project-local headers. #include#include #include #include #include #include #endif
我总是使用最小耦合原理.如果当前文件实际需要,我只包含一个文件; 如果我可以使用前向声明而不是完整定义,我将使用它.我的.cpp文件总是在顶部有一堆#includes.
Bar.h:
class Foo; class Bar { Foo * m_foo; };
Bar.cpp:
#include "Foo.h" #include "Bar.h"
仅使用所需的最少量包含.无用包括减慢编译速度.
此外,如果只需要指向类,则不必包含标题.在这种情况下,您可以使用前向声明,如:
class BogoFactory;
编辑:只是为了说清楚.当我说最低金额时,我并不是说建筑包括如下链:
a.h #include "b.h" b.h #include "c.h"
如果啊需要ch,它当然需要包括在啊以防止维护问题.