C++ 在头文件与源文件中包含 #includes

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2596449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:01:42  来源:igfitidea点击:

Including #includes in header file vs source file

c++fileheaderinclude

提问by Rob from Utah

I like to put all my #includes in my header file then only include my header for that source file in my source file. What is the industry standard? Are there any draw backs to my method?

我喜欢把我所有的#includes 放在我的头文件中,然后只在我的源文件中包含我的源文件的头文件。什么是行业标准?我的方法有什么缺点吗?

回答by tzaman

Generally, you only want to put the minimum necessary includes into a class header file, as anyone else who uses that header will be forced to #includeall of them too. In larger projects, this leads towards slower builds, dependency issues, and all sorts of other nastiness.

通常,您只想将最少的必要包含放入类头文件中,因为使用该头文件的任何其他人也将被迫使用#include所有这些头文件。在较大的项目中,这会导致构建速度变慢、依赖性问题和各种其他问题。

Think of a header file as the public interface to your class. You don't want to saddle everyone who uses it with extra dependencies, unless they're necessaryto be able to use the class.

将头文件视为类的公共接口。您不想让使用它的每个人都具有额外的依赖项,除非他们必须能够使用该类。

Move anything that's only needed in the class implementation down into the source file. For other classes used in a header, only #includetheir headers if you actually need to know their size or contents in the header- anything else and a forward declarationis sufficient. Most cases, you only need to #includeclasses you're inheriting from, and classes whose objects are value members of your class.

将仅在类实现中需要的任何内容下移到源文件中。对于标题中使用的其他类,#include如果您确实需要知道它们的大小或标题中的内容,则只有它们的标题- 任何其他内容和前向声明就足够了。大多数情况下,您只需要#include继承自的类,以及其对象是您的类的值成员的类。

This pagehas a good summary. (Replicated below for reference)

这个页面有一个很好的总结。(以下复制以供参考)



C++ Header File Include Patterns #

C++ 头文件包含模式 #

Large software projects require a careful header file management even when programming in C. When developers move to C++, header file management becomes even more complex and time consuming. Here we present a few header file inclusion patterns that will simplify this chore.

即使在使用 C 编程时,大型软件项目也需要仔细的头文件管理。当开发人员转向 C++ 时,头文件管理变得更加复杂和耗时。在这里,我们展示了一些头文件包含模式,可以简化这项工作。

Header File Inclusion Rules

头文件包含规则

Here, we discuss the basic rules of C++ header file inclusion needed to simplify header file management.

在这里,我们讨论简化头文件管理所需的 C++ 头文件包含的基本规则。

A header file should be included only when a forward declaration would not do the job. The header file should be so designed that the order of header file inclusion is not important. This is achieved by making sure that x.his the first header file in x.cppThe header file inclusion mechanism should be tolerant to duplicate header file inclusions. The following sections will explain these rules with the help of an example.

仅当前向声明无法完成这项工作时,才应包含头文件。头文件的设计应该使头文件的包含顺序不重要。这是通过确保 头文件包含机制应该容忍重复的头文件包含中x.h的第一个头文件来实现的x.cpp。以下部分将通过示例来解释这些规则。

Header File Inclusion Example

头文件包含示例

The following example illustrates different types of dependencies. Assume a class A with code stored in a.cppand a.h.

以下示例说明了不同类型的依赖项。假设一个类 A 的代码存储在a.cpp和 中a.h

a.h

a.h

#ifndef _a_h_included_
#define _a_h_included_
#include "abase.h"
#include "b.h"

// Forward Declarations
class C;
class D;

class A : public ABase
{
  B m_b;
  C *m_c;
  D *m_d;

public:
  void SetC(C *c);
  C *GetC() const;

  void ModifyD(D *d);
};
#endif

a.cpp

a.cpp

#include "a.h"
#include "d.h"

void A::SetC(C* c)
{
  m_c = c;
}

C* A::GetC() const
{
  return m_c;
}

void A::ModifyD(D* d)
{
  d->SetX(0);
  d->SetY(0);
  m_d = d;
}

File Inclusion Analysis

文件包含分析

Lets analyze the header file inclusions, from the point of view of classes involved in this example, i.e. ABase, A, B, Cand D.

让分析头文件夹杂物,从所涉及在该示例中的类,即,点ABaseABCD

  • Class ABase:ABaseis the base class, so the class declaration is required to complete the class declaration. The compiler needs to know the size of ABaseto determine the total size of A. In this case abase.hshould be included explicitly in a.h.
  • Class B:Class Acontains Class Bby value , so the class declaration is required to complete the class declaration. The compiler needs to know the size of B to determine the total size of A. In this case b.hshould be included explicitly in a.h.
  • Class C: Class Cis included only as a pointer reference. The size or actual content of Care not important to a.hor a.cpp. Thus only a forward declaration has been included in a.h. Notice that c.hhas not been included in either a.hor a.cpp.
  • Class D: Class Dis just used as a pointer reference in a.h. Thus a forward declaration is sufficient. But a.cppuses class Din substance so it explicitly includes d.h.
  • Class ABase:ABase是基类,所以需要类声明来完成类声明。编译器需要知道 的大小ABase来确定 的总大小A。在这种情况下,abase.h应明确包含在a.h.
  • Class B:ClassA包含 Class Bby value ,所以需要类声明来完成类声明。编译器需要知道 B 的大小来确定A. 在这种情况下,b.h应明确包含在a.h.
  • C 类Class C仅作为指针引用包含在内。的大小或实际内容Ca.h或不重要a.cpp。因此,仅包含一个前向声明a.h。请注意,c.h未包含在a.h或 中a.cpp
  • 类 D:类Da.h. 因此,预先声明就足够了。但实质上a.cpp使用类D,因此它明确包含d.h.

Key Points

关键点

Header files should be included only when a forward declaration will not do the job. By not including c.hand d.hother clients of class Anever have to worry about c.hand d.hunless they use class C and D by value. a.hhas been included as the first header file in a.cppThis will make sure that a.hdoes not expect a certain header files to be included before a.h. As a.hhas been included as the first file, successful compilation of a.cppwill ensure that a.hdoes not expect any other header file to be included before a.h. If this is followed for all classes, (i.e. x.cppalways includes x.has the first header) there will be no dependency on header file inclusion. a.hincludes the check on preprocessor definition of symbol _a_h_included_. This makes it tolerant to duplicate inclusions of a.h.

仅当前向声明不起作用时才应包含头文件。通过不包括c.hd.h其他类的客户A永远不必担心c.h并且d.h除非他们按值使用类 C 和 D。 a.h已经作为第一个头文件包含在a.cpp这将确保a.h不期望某个头文件被包含在之前a.h。由于a.h已作为第一个文件被包含,成功编译a.cpp将确保a.ha.h. 如果所有类都遵循这一点(即x.cpp始终包含x.h作为第一个头文件),则将不依赖于头文件包含。 a.h包括检查符号的预处理器定义_a_h_included_。这使得它可以容忍 的重复包含a.h

Cyclic Dependency

循环依赖

Cyclic dependency exists between class Xand Yin the following example. This dependency is handled by using forward declarations.

在类XY以下示例之间存在循环依赖。这种依赖是通过使用前向声明来处理的。

x.h and y.h

x.h and y.h

/* ====== x.h ====== */
// Forward declaration of Y for cyclic dependency
class Y;

class X 
{
    Y *m_y;
    ...
};

/* ====== y.h ====== */
// Forward declaration of X for cyclic dependency
class X;

class Y 
{
    X *m_x;
    ...
};