在头文件和源文件中包含

在头文件和源文件中包含

本文介绍了在头文件和源文件中包含#includes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢将我所有的#包括在我的头文件中,然后在源文件中只包含我的头文件。什么是行业标准?有没有退缩到我的方法?

解决方案

通常,您只想将最小必要的包括到类头文件,因为使用该头文件的其他人也将被强制为 #include 。在较大的项目中,这会导致构建更慢,依赖性问题以及各种其他问题。

将头文件视为您班级的公共接口。您不希望为每个使用它的人提供额外的依赖关系,除非他们必要才能使用该类。

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



有一个好的总结。 (复制如下以供参考)

$ h
$ b

C ++头文件包含模式#



大型软件项目需要小心的头文件管理,即使用C编程。当开发人员转向C ++时,头文件管理变得更加复杂和耗时。这里我们给出几个头文件包含模式,这将简化这件事。



头文件包含规则



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



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

头文件包含示例



a.cpp 和 ah 中。



ah



  #ifndef _a_h_included_ 
#define _a_h_included_
#includeabase.h
#includebh

//正向声明
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



  #includeah
#includedh

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



文件包含分析



从本例中涉及的类的角度(即 ABase , A )分析头文件包含>, B , C 和 D 。




  • ABase ABase 是基类,所以类声明是完成类声明所必需的。编译器需要知道 ABase 的大小,以确定 A 的总大小。在这种情况下, abase.h 应明确包含在 ah 中。

  • Class B :类 A 包含Class B 值,所以需要类声明完成类声明。编译器需要知道B的大小以确定 A 的总大小。在这种情况下, bh 应明确包含在 ah 中。

  • Class C : Class C 仅作为指针引用。 C 的大小或实际内容对于 ah 或 a.cpp 。因此在 a.h 中只包含一个前向声明。请注意, ch 未包含在 ah 或 a.cpp
  • D类:Class D 仅用作啊。因此前向声明就足够了。但 a.cpp 实质上使用class D ,所以它明确包含 dh

    要点



    头文件应该只包含在内当一个前向声明不会完成这项工作时。通过不包括 ch 和 dh 类 A 除非按值C和D使用类别,否则不必担心 ch 和 dh 。
    ah 已被包含在 a.cpp中的第一个头文件这将确保 ah 并不期望在 ah 之前包含某些头文件。由于 ah 已被包含为第一个文件,所以 a.cpp 的成功编译将确保 > ah 并不期望在 ah 之前包含任何其他头文件。
    如果所有类都遵循这个规则(即 x.cpp 总是包含 xh )作为第一个头)将不会依赖头文件包含。
    a.h 包括对符号 _a_h_included _ 的预处理器定义的检查。这使得它可以容忍重复包含 ah 。



    循环依赖



    在以下示例中,类 X 和 Y 之间存在循环依赖关系。



    xh和yh


    $ b这个依赖关系是通过使用前向声明来处理的。 $ b

      / * ====== xh ====== * / 
    //用于循环依赖的Y的前向声明
    class Y ;

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

    / * ====== y.h ====== * /
    //用于循环依赖的X的前向声明
    class X;

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


    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?

    解决方案

    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.

    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.

    Header File Inclusion Rules

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

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

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

    • 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.
    • 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.
    • 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.
    • 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.

    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.

    Cyclic Dependency

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

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

    这篇关于在头文件和源文件中包含#includes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 23:44