代码之家  ›  专栏  ›  技术社区  ›  Navaneeth K N

使用C++头文件[关闭]的最佳实践

  •  20
  • Navaneeth K N  · 技术社区  · 16 年前

    我对头文件的使用有以下疑问。

    1-包括在评论后放置防护装置

    /* Copyright Note and licence information (multiple lines) */
    #ifndef FOO_H
    #define FOO_H
    // Header file contents
    #endif
    

    Habor萨特在他的《C++编码标准》一书中说,上面提到的代码是有问题的。他说“ifndef”语句应该出现在头文件的第一行。我觉得这没有说服力。头文件里有你们这些人吗?

    2-在头文件中使用命名空间

    #ifndef FOO_H
    #define FOO_H
    namespace FooNameSpace{
        // Header file contents
    }
    #endif
    

    上述守则是否采用正确的做法?我是说,你在头文件中使用名称空间吗?我知道为什么在头文件中导入名称空间是没有意义的,但是像上面这样的声明呢?

    如果上面的方法是正确的,你怎么办 远期申报 “属于另一个命名空间中的类?是不是像

    #ifndef FOO_H
    #define FOO_H
    namespace AnotherNameSpace{
        class AnotherFoo; // forward declaration
    }
    
    namespace FooNameSpace{
        // Use AnotherFoo here
    }
    #endif
    

    “那” 远期申报 “是唯一要避免的方法” 循环依赖 “,对吗?

    5 回复  |  直到 14 年前
        1
  •  18
  •   Adam Rosenfield    16 年前
    1. include守卫和评论的顺序纯粹是一个风格问题——它不会对编译速度产生任何可测量的影响。

    2. 名称空间绝对应该在头文件中用于声明函数、类、全局变量等 做就是用 using 头文件中的语句——不可能使用包含它的源文件中的某些内容,也不应该强制includers向全局范围添加额外的内容。如果需要在头文件中使用其他名称空间中的内容,请完全限定每个名称。有时候会很痛苦,但这确实是正确的做法。

    示例:

    // WRONG!
    using namespace std;
    class MyClass
    {
        string stringVar;
    };
    
    // RIGHT
    class MyClass
    {
        std::string stringVar;
    };
    

    至于其他名称空间中类的前向声明,您完全正确。只要记住总是合格的 AnotherFoo 作为 AnotherNameSpace::AnotherFoo 当你在标题中引用它时。实际上,前向声明是打破循环依赖关系的唯一方法。

        2
  •  7
  •   Michael Burr    16 年前
    1. 我听说有评论 在include guard引起 一些编译器会错过 优化。如果警卫是 首先,编译器可以 认得这个成语 麻烦打开标题 后续包括。在我自己身上 代码,注释通常位于 包括警卫。我从来没有 费心测试看看这是否 有没有影响。我可能永远不会(但如果有人这么做,我会对结果感兴趣)。

    2. 当然,标题应该包含 名称空间-否则没有 有用的可能在 命名空间。但是,作为你 提到,标题不应该 “导入”(因为缺少更好的词) 将命名空间转换为编译单元 带一个' using '指令。

        3
  •  3
  •   Uri    16 年前

    关于#1,我不知道有任何具体的支持或反对理由。许多公司都有这样一个政策,即版权声明必须是文件中的第一项,然后才是其他内容或任何有意义的代码(可能假设您在吸收任何代码之前都会阅读版权)。为此,IFNDEF已经是代码了。从可用性的角度来看,把版权放在首位是有意义的,因为人们忽视了版权。然而,在我看来,任何描述模块的东西都应该在ifndef之后。

        4
  •  2
  •   Joseph Garvin    16 年前

    1)由于评论实际上没有任何作用,我怀疑它有多重要。不过,从技术上讲,#包括复制和粘贴,因此将注释放在头保护之外可能意味着预处理器要做更多的工作。我不知道大多数编译器是否足够聪明,能够对此进行优化(即,如果它们在预处理器步骤之前删除注释),但在达到上万个头文件之前,您可能不会注意到。

    2)没错。如果你想把一个类放在一个名称空间中,并且这个类要在头文件中声明,那么它应该在名称空间中声明,因此应该在头文件中。是的,这就是你申报的方式。是的,它是避免循环依赖的主要工具(您也可以更改您的设计,但原则上循环没有错,前提是这两个类只是通过引用或指针相互引用,而不调用任何方法)。

        5
  •  2
  •   kal    16 年前
    1. 我不认为添加评论对性能有任何影响,正如亚当对本文的回答所指出的那样。

    2. 我在头文件中使用了自己的名称空间,如果您定义了自己的字符串类,那么它将与std名称空间字符串类冲突。

    准确地使用“Using”关键字并没有错(因为它为您提供了很多便利,而且在所有变量之前键入的内容也少得多)