代码之家  ›  专栏  ›  技术社区  ›  liaK

头文件包含/转发声明

  •  11
  • liaK  · 技术社区  · 16 年前

    在我的C++项目中,什么时候我必须使用包含? #include "myclass.h" )头文件?我什么时候要用班前声明( class CMyClass; )?

    5 回复  |  直到 10 年前
        1
  •  19
  •   Charles Beattie    10 年前

    一般来说,首先尝试转发声明。这将减少编译时间等。如果不编译,请转到 #include . 如果您需要执行以下任一操作,则必须执行包括:

    1. 访问类的成员或函数。
    2. 使用指针算术。
    3. 使用SIZEOF。
    4. 任何RTTI信息。
    5. new / delete 复制等。
    6. 按值使用。
    7. 从中继承。
    8. 把它作为一个成员。
    9. 函数中的实例。

    (来自@moing duck的6,7,8,9)

    他们可能更多,但我今天没戴语言法帽。

        2
  •  11
  •   Peter O. Manuel Pinto    14 年前

    转发申报存在几个问题:

    • 这就像将类名存储在多个地方——如果在一个地方更改类名,那么现在必须在其他地方更改它。重构成为一个挑战,因为代码仍然可以用更改的类名进行良好的编译,但是链接将失败,因为前向声明引用了未定义的类。如果包含头文件并且不使用前向声明,则在编译期间将捕获这些问题。
    • 远期申报对其他人来说很难维持。例如,如果头文件包含:

      include "MyProject/MyWidgets/MyFooWidgets/FooUtil/Foo.h"
      

      而不是远期申报

       class Foo ;  
      

      其他人很容易找到声明foo类的位置。有了远期申报,就不是这样了 很明显;当用户试图打开时,一些IDE(如Eclipse)可能会打开forward声明。 变量的声明。

    • 如果代码中包含包含转发声明的头文件,但实际的代码定义位于未链接的其他库中,则链接可能会失败,并出现未定义的符号错误。在编译时用诸如 "Could not find file MyProject/MyWidgets/MyFooWidgets/FooUtil/Foo.h" 从那时起,你就知道在哪里可以找到相应的 Foo.cpp 并确定包含它的库。

    如果您认为您的构建花费了太长时间,那么尝试只在没有链接的情况下进行编译。如果您的代码需要10秒的编译时间和10分钟的链接时间,那么这个问题与一些额外的包含无关。同样,如果头文件中包含的内容太多,以至于实际上导致了性能问题,那么您可能需要将该文件的内容重构为多个较小的头文件。

    那么,什么时候可以转发申报呢?如果在与实际声明相同的头文件中执行此操作。

    例子:

    class Foo ;
    
    typedef Foo* FooPtr ;
    typedef Foo& FooRef ;
    
    class Foo
    {
       public:
          Foo( ) ;
          ~Foo( ) ;
    }
    

    class TreeNode ;
    
    class Tree
    {
    private:
       TreeNode m_root ;
    }
    
    class TreeNode
    {
       void* m_data ;
    } ;
    
        3
  •  10
  •   ypnos    16 年前

    如果您只需要一个指向类的指针,而不需要任何关于类的知识,而不需要它的名称,那么您可以使用forward声明。

        4
  •  2
  •   anon    16 年前

    作为一个初学者,当您需要使用它们包含的类型或函数时,您应该始终包含头文件-不要试图通过前向声明来“优化”您的构建-这几乎从来没有必要,即使是在大型项目上,只要项目的架构良好。

    您唯一需要转发声明的时间是这样的情况:

    struct A {
       void f( B b );
    };
    
    struct B {
       void f( A a );
    };
    

    其中每个结构(或类)引用另一个结构的类型。在这种情况下,您需要B的前向声明来解决问题:

    struct B;   // forward declaration
    
    struct A {
       void f( B b );
    };
    
    struct B {
       void f( A a );
    };
    
        5
  •  2
  •   Pontus Gagge    16 年前

    你应该努力将你的 #include 既可以减少编译时间,也可以帮助实现模块化和可测试性。正如@ypnos所说,当你只需要指针时,类转发是非常好的。

    有关如何减少头依赖性的一些实用提示,请参见例如。 this article .

    推荐文章