繁体   English   中英

为什么在头文件之上包含指令?

[英]Why are include directives on top of header files?

我曾经在编程类中告诉过,C ++通过让程序员在函数块中的任何地方声明其变量来实现更好的可读性。 这样,变量就与处理它的代码部分组合在一起。

为什么我们不为包括做同样的事情? 换句话说,为什么不鼓励将include文件放在实际使用它的定义旁边?

parser::parser()
{
  // some initialization goes there which does not make use of regex
}

#include <boost/regex.hpp>
parser::start()
{
  // here we need to use boost regex to parse the document
}

其中一个原因是#include是无上下文的,它们只是纯文本包含,并且在代码中间使用它可能会产生一些不必要的影响。 例如,考虑您有一个命名空间,并且此文件中的所有代码都属于命名空间:

// Include on demand:
namespace ns {
   void f() {} // does not need anything
//... lots of other lines of code
#include <vector>
   void g() { std::vector<int> v; }
}

现在甚至可能编译好......而且错了。 因为包含在命名空间内,所以文件的内容被转储到ns ,包含的文件声明/ definitions ::ns::std::vector 因为它只是标题,它甚至可以编译正常,只有当你尝试在具有不同子系统的接口中使用它时(在不同的命名空间中)才会失败 - 这可以修复,你只需关闭所有上下文,添加包含并重新打开相同的上下文......

在其他情况下,翻译单元中的代码可能实际上会影响包含。 例如,考虑在翻译单元中添加了using namespace指令。 之后包含的任何标头都将using namespace指令,这也可能产生不需要的效果。

它也可能以不同的方式更容易出错。 考虑两个标头,为intdouble定义f不同重载。 您可以在文件的开头添加一个(比如int版本)并使用它,然后添加另一个并使用它。 现在,如果你在包含第二个标题的行上方调用f(5.0) ,那么int版本将被调用 - 此时编译器只能使用过载 - 这将是一个难以捕获的错误。 完全相同的代码行在文件的不同位置具有完全不同的含义(诚然已经是这种情况,但在文件中的声明中,更容易找到被拾取的那个以及为什么)

通常,包含声明要在组件中使用的元素,并将它们放在顶部,快速浏览一下依赖项列表。

想象一下以下文件:

#include <someheader>

namespace myns {
  void foo() {
  }

  void bar() {
    // call something from someheader:
    func();
  }
}

#include <someheader>放在使用点附近可能很诱人。 如果您编写以下代码,那就没问题了:

namespace myns {
  void foo() {
  }
}

#include <someheader>

namespace myns {      
  void bar() {
    // call something from someheader:
    func();
  }
}

问题出在中型/大型文件中,根据您的缩进样式,很容易忽略您在命名空间(以及其他#ifdef s)中嵌套的深度。 您可能稍后回来并决定移动,或添加另一个嵌套命名空间。

所以,如果你把#include写在最顶层总是你不会因为不小心写下这样的东西而被咬伤:

namespace myns {
  void foo() {
  }

// Whoops, this shouldn't be inside myns at all!
#include <someheader>

  void bar() {
    // call something from someheader:
    func();
  }
}

根据<someheader>究竟是什么,这将介于错误和非常错误之间。 (例如,您可以通过违反具有多个定义的ODR来结束UB,尽管其他合法且相同的令牌序列匹配不同的功能,因此违反了§3.2.5)。

这是不鼓励的,因为大多数程序员习惯于包含在文件的顶部。 我认为习惯的力量,与99%的现有代码保持一致。

当我个人想看看包含哪些标题时,我只看顶部。 在特殊(并且非常少见)的情况下,有些东西是可疑的,我可能会在整个文件中寻找包含。

无论如何,对于编译器来说它没有任何区别。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM