包含在头文件和源文件中的#。

时间:2022-03-03 15:06:44

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?

我喜欢把所有的#include放在头文件中,然后只在源文件中包含该源文件的头文件。什么是行业标准?我的方法有什么吸引人的地方吗?

1 个解决方案

#1


44  

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 #include all of them too. In larger projects, this leads towards slower builds, dependency issues, and all sorts of other nastiness.

通常,您只希望将最小必需的内容包含到一个类头文件中,因为任何使用该头的人都将被强制包含所有这些内容。在更大的项目中,这会导致构建更慢、依赖性问题以及其他各种各样的不稳定性。

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 necessary to 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 #include their headers if you actually need to know their size or contents in the header - anything else and a forward declaration is sufficient. Most cases, you only need to #include classes you're inheriting from, and classes whose objects are value members of your class.

将类实现中只需要的任何东西移动到源文件中。对于header中使用的其他类,只有#包含它们的头,如果您实际上需要知道它们的大小或标题中的内容—任何其他的和一个forward声明就足够了。大多数情况下,您只需要#包含您继承的类,类的对象是类的值成员。

This page has a good summary. (Replicated below for reference)

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


C++ Header File Include Patterns #

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.h is the first header file in x.cpp The 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中的第一个头文件。头文件包含机制应该能够容忍重复的头文件包含。下面的部分将在一个示例的帮助下解释这些规则。

Header File Inclusion Example

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

下面的例子演示了不同类型的依赖关系。假设a类有存储在a中的代码。cpp和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

#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, C and D.

让我们从本例中涉及的类的角度,即ABase, A, B, C和D,来分析头文件包含的内容。

  • Class ABase: ABase is the base class, so the class declaration is required to complete the class declaration. The compiler needs to know the size of ABase to determine the total size of A. In this case abase.h should be included explicitly in a.h.
  • 类ABase: ABase是基类,因此需要类声明来完成类声明。编译器需要知道ABase的大小以确定a的总大小。h应该明确地包含在a.h中。
  • Class B: Class A contains Class B by 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.h should be included explicitly in a.h.
  • B类:A类按值包含类B,因此需要类声明来完成类声明。编译器需要知道B的大小以确定a的总大小。h应该明确地包含在a.h中。
  • Class C: Class C is included only as a pointer reference. The size or actual content of C are not important to a.h or a.cpp. Thus only a forward declaration has been included in a.h. Notice that c.h has not been included in either a.h or a.cpp.
  • 类C:类C仅包含作为指针引用。C的大小或实际内容对a不重要。h或a.cpp。因此,在a.h中只包含了一个前向声明。注意c。h没有包含在a中。h或a.cpp。
  • Class D: Class D is just used as a pointer reference in a.h. Thus a forward declaration is sufficient. But a.cpp uses class D in substance so it explicitly includes d.h.
  • 类D: D类只是在a.h中用作指针引用,因此前一个声明就足够了。但一个。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.h and d.h other clients of class A never have to worry about c.h and d.h unless they use class C and D by value. a.h has been included as the first header file in a.cpp This will make sure that a.h does not expect a certain header files to be included before a.h. As a.h has been included as the first file, successful compilation of a.cpp will ensure that a.h does not expect any other header file to be included before a.h. If this is followed for all classes, (i.e. x.cpp always includes x.h as the first header) there will be no dependency on header file inclusion. a.h includes the check on preprocessor definition of symbol _a_h_included_. This makes it tolerant to duplicate inclusions of a.h.

只有当转发声明不能完成任务时,才应该包含头文件。不包括c。h和d。A类的其他客户永远不用担心c。h和d。除非他们用C和D来表示。一个。h已经作为第一个头文件包含在a中。这将确保a。h不期望在a.h之前包含特定的头文件。h已被包括为第一个文件,成功编译a。cpp将确保a。h不期望在a.h之前包含任何其他头文件,如果这是对所有类的跟踪,(即x)。cpp总是包括x。h作为第一个标题)将不依赖于头文件包含。一个。h包括对符号_a_h_included_的预处理器定义的检查。这使它能容忍a.h的重复内含物。

Cyclic Dependency

Cyclic dependency exists between class X and Y in the following example. This dependency is handled by using forward declarations.

在下面的示例中,类X和Y之间存在循环依赖关系。这种依赖关系是通过使用forward声明来处理的。

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;
    ...
};

#1


44  

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 #include all of them too. In larger projects, this leads towards slower builds, dependency issues, and all sorts of other nastiness.

通常,您只希望将最小必需的内容包含到一个类头文件中,因为任何使用该头的人都将被强制包含所有这些内容。在更大的项目中,这会导致构建更慢、依赖性问题以及其他各种各样的不稳定性。

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 necessary to 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 #include their headers if you actually need to know their size or contents in the header - anything else and a forward declaration is sufficient. Most cases, you only need to #include classes you're inheriting from, and classes whose objects are value members of your class.

将类实现中只需要的任何东西移动到源文件中。对于header中使用的其他类,只有#包含它们的头,如果您实际上需要知道它们的大小或标题中的内容—任何其他的和一个forward声明就足够了。大多数情况下,您只需要#包含您继承的类,类的对象是类的值成员。

This page has a good summary. (Replicated below for reference)

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


C++ Header File Include Patterns #

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.h is the first header file in x.cpp The 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中的第一个头文件。头文件包含机制应该能够容忍重复的头文件包含。下面的部分将在一个示例的帮助下解释这些规则。

Header File Inclusion Example

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

下面的例子演示了不同类型的依赖关系。假设a类有存储在a中的代码。cpp和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

#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, C and D.

让我们从本例中涉及的类的角度,即ABase, A, B, C和D,来分析头文件包含的内容。

  • Class ABase: ABase is the base class, so the class declaration is required to complete the class declaration. The compiler needs to know the size of ABase to determine the total size of A. In this case abase.h should be included explicitly in a.h.
  • 类ABase: ABase是基类,因此需要类声明来完成类声明。编译器需要知道ABase的大小以确定a的总大小。h应该明确地包含在a.h中。
  • Class B: Class A contains Class B by 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.h should be included explicitly in a.h.
  • B类:A类按值包含类B,因此需要类声明来完成类声明。编译器需要知道B的大小以确定a的总大小。h应该明确地包含在a.h中。
  • Class C: Class C is included only as a pointer reference. The size or actual content of C are not important to a.h or a.cpp. Thus only a forward declaration has been included in a.h. Notice that c.h has not been included in either a.h or a.cpp.
  • 类C:类C仅包含作为指针引用。C的大小或实际内容对a不重要。h或a.cpp。因此,在a.h中只包含了一个前向声明。注意c。h没有包含在a中。h或a.cpp。
  • Class D: Class D is just used as a pointer reference in a.h. Thus a forward declaration is sufficient. But a.cpp uses class D in substance so it explicitly includes d.h.
  • 类D: D类只是在a.h中用作指针引用,因此前一个声明就足够了。但一个。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.h and d.h other clients of class A never have to worry about c.h and d.h unless they use class C and D by value. a.h has been included as the first header file in a.cpp This will make sure that a.h does not expect a certain header files to be included before a.h. As a.h has been included as the first file, successful compilation of a.cpp will ensure that a.h does not expect any other header file to be included before a.h. If this is followed for all classes, (i.e. x.cpp always includes x.h as the first header) there will be no dependency on header file inclusion. a.h includes the check on preprocessor definition of symbol _a_h_included_. This makes it tolerant to duplicate inclusions of a.h.

只有当转发声明不能完成任务时,才应该包含头文件。不包括c。h和d。A类的其他客户永远不用担心c。h和d。除非他们用C和D来表示。一个。h已经作为第一个头文件包含在a中。这将确保a。h不期望在a.h之前包含特定的头文件。h已被包括为第一个文件,成功编译a。cpp将确保a。h不期望在a.h之前包含任何其他头文件,如果这是对所有类的跟踪,(即x)。cpp总是包括x。h作为第一个标题)将不依赖于头文件包含。一个。h包括对符号_a_h_included_的预处理器定义的检查。这使它能容忍a.h的重复内含物。

Cyclic Dependency

Cyclic dependency exists between class X and Y in the following example. This dependency is handled by using forward declarations.

在下面的示例中,类X和Y之间存在循环依赖关系。这种依赖关系是通过使用forward声明来处理的。

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;
    ...
};