C++ C++;标题-包括标题时的最佳做法

C++ C++;标题-包括标题时的最佳做法,c++,header,C++,Header,C++标题 如果我有A.cpp和A.h以及b.h,c.h,d.h 我应该做: 在A.h.中: #include "b.h" #include "c.h" #include "d.h" 在A.cpp中: #include "A.h" #include "A.h" #include "b.h" #include "c.h" #include "d.h" 或 在A.cpp中: #include "A.h" #include "A.h" #include "b.h" #include "c.h"

C++标题

如果我有A.cpp和A.h以及b.h,c.h,d.h

我应该做:

在A.h.中:

#include "b.h"
#include "c.h"
#include "d.h"
在A.cpp中:

#include "A.h"
#include "A.h"
#include "b.h"
#include "c.h"
#include "d.h"

在A.cpp中:

#include "A.h"
#include "A.h"
#include "b.h"
#include "c.h"
#include "d.h"

是否存在性能问题?明显的好处?这有什么不好的地方吗?

不希望在其他头中包含头-这会减慢编译速度,至少循环引用不会有性能问题,这都是在编译时完成的,您的头应该设置为不能包含多次


我不知道是否有一种标准的方法可以做到这一点,但我更喜欢在源文件中包含我需要的所有头文件,如果头文件本身需要它(例如,来自不同头文件的typedef),则将它们包含在头文件中。

您应该只包含编译所需的内容;添加不必要的include会影响编译时间,尤其是在大型项目中

每个头文件都应该能够自己干净地编译——也就是说,如果您有一个只包含该头文件的源文件,那么它应该编译时不会出错。头文件中不应包含超出此要求的内容

尽量使用前向声明。如果您正在使用一个类,但头文件只处理指向该类对象的指针/引用,那么就不需要包含该类的定义——只需使用一个转发声明:

class SomeClass;
// Can now use pointers/references to SomeClass
// without needing the full definition

亚当·罗森菲尔德告诉你的是正确的。可以使用转发声明的示例如下:

#ifndef A_H_
#define A_H_

    #include "D.h"
    class B;  //forward declaration
    class C;  //forward declaration

    class A
    {
    B *m_pb;  //you can forward declare this one bacause it's a pointer and the compilier doesn't need to know the size of object B at this point in the code.  include B.h in the cpp file.
    C &m_rc;  //you can also forware declare this one for the same reason, except it's a reference.

    D m_d;    //you cannot forward declare this one because the complier need to calc the size of object D.

    };

#endif

这里的关键做法是在每个foo.h文件周围设置一个保护,例如:

#ifndef _FOO_H
#define _FOO_H

...rest of the .h file...
#endif
这就防止了多重包裹、循环和所有这些伴随而来的恐怖。一旦确保每个include文件都受到保护,那么细节就不那么重要了

我喜欢Adam所表达的一个指导原则:确保如果源文件只包含
a.h
,那么它不会因为
a.h
而不可避免地出错,前提是之前已经包含了其他文件——例如,如果
a.h
要求之前包含
b.h
,那么它可以也应该只包含b.h本身(如果b.h之前已经包括在内,警卫会将其视为noop)

反之亦然,源文件应该包含它需要的某些东西(宏、声明等)的头,而不是假设其他头只是神奇地出现,因为它包含了一些


如果你是按值使用类,唉,你需要在你包含的一些
.h
中包含类的所有血淋淋的细节。但是对于通过引用或指针的某些使用,只需一个简单的
类sic;
就足够了。例如,如果类a可以通过指向类b实例的指针逃过一劫,那么所有其他条件都是相同的(即,成员
b类*my_bp;
而不是成员
b类*my_b;
)可以使包含文件之间的耦合变弱(减少大量重新编译)--例如,
b.h
可能比
b类多一点;
而所有血淋淋的细节都在
b\u impl.h
中,只有在真正需要它的标题中才包括它…

答案:让
A.h
包括
b.h
c.h
d.h
只有在需要使构建成功的情况下才包括f thumb is:在头文件中只包含必要的代码。在
a.h
中不立即需要的任何内容都应包含在
a.cpp

推理:头文件中包含的代码越少,在某个地方做了一些更改后,就越不可能重新编译使用头文件的代码。如果不同头文件之间存在大量的
#include
引用,则更改其中任何一个头文件都需要重新生成包含更改的hea的所有其他文件因此,如果您决定接触某个顶级头文件,这可能会重建代码的大部分

通过尽可能在头文件中使用,可以减少源文件的耦合,从而加快生成速度。此类前向声明可用于比您想象的更多的情况。根据经验,如果需要,您只需要头文件
t.h
(定义类型
t

  • 声明类型为
    T
    的成员变量(注意,这不包括声明指向-
    T
    的指针)
  • 编写一些内联函数,用于访问类型为
    T
    的对象的成员
  • 如果头文件只是

  • 声明构造函数/函数,这些构造函数/函数获取对
    T
    对象的引用或指针
  • 声明通过指针、引用或值返回
    T
    对象的函数
  • 声明作为
    T
    对象的引用或指针的成员变量
  • 考虑这个类声明;您真的需要包含
    A
    B
    C
    的哪些文件

    class MyClass
    {
    public:
        MyClass( const A &a );
    
        void set( const B &b );
        void set( const B *b );
        B getB();
        C getC();
    
    private:
        B *m_b;
        C m_c;
    };
    

    您只需要类型
    C
    的include文件,因为成员变量
    m_C
    。您通常也可以通过不直接声明成员变量而使用隐藏私有结构中的所有成员变量来删除此要求,以便它们不再显示在头文件中。

    @mgd-如果我如果一个头有10个包含,而源有10个不同的包含,我是否应该将包含从头移动到源,这样源就有20个包含?请参阅alex更完整的回答。一个例外是,如果您有预编译的头,在这种情况下,包括所有永远不会变为一个的平台/框架/操作系统头归档并包括everywhere@Jeff-啊,对了,标题中的项目可能需要它。但是如果所有标题都在源文件中,他们不会得到它吗?@Adam-你有前向声明的例子吗?什么时候合适,什么时候不合适?很好