繁体   English   中英

包含在 header 文件中

Includes within header files

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

header 文件应该有#include吗?

我通常认为这种分层包含是不好的。 假设你有这个:

富.h:

#include <stdio.h> // we use something from this library here
struct foo { ... } foo;

main.c

#include "foo.h"
/* use foo for something */
printf(...)

当 main.c 的实现发生变化,你不再使用 foo.h 时,编译会中断,你必须手动添加<stdio.h>

与拥有这个相比:

foo.h

// Warning! we depend on stdio.h
struct foo {...

main.c

#include <stdio.h> //required for foo.h, also for other stuff
#include "foo.h"

当你停止使用 foo 时,删除它不会破坏任何东西,但是删除 stdio.h 会破坏 foo.h。

应该从.h 文件中禁止#includes 吗?

6 个回复

你已经概述了关于这个主题的两种主要哲学。

我自己的观点(我认为这就是人们真正可以拥有的全部)是标题应该尽可能独立。 我不想为了能够使用 header 而知道foo.h的所有依赖项。 我也鄙视必须以特定顺序包含标题。

然而, foo.h的开发者也应该负责使其尽可能地无依赖。 例如,如果可能的话,应该将foo.h header 编写为不依赖于stdio.h (使用前向声明可以帮助实现这一点)。

请注意,C 标准禁止一个标准 header 包含另一个标准 header,但 ZF6F097C9FDCF1F883 标准没有2C 因此,当从一个 C++ 编译器版本迁移到另一个编译器版本时,您可以看到您描述的问题。 例如,在 MSVC 中,包括用于引入<iterator><vector> ,但在 MSVC 2010 中不再出现,因此之前编译的代码可能不再存在,因为您可能需要专门包含<iterator>

然而,尽管 C 标准似乎提倡第二种理念,但请注意,它还要求没有 header 依赖于另一个标准,并且您可以以任何顺序包含标题。 因此,您可以两全其美,但代价是 C 库的实现者的复杂性。 他们必须跳过一些障碍才能做到这一点(特别是为了支持可以通过多个标头中的任何一个引入的定义,例如NULLsize_t )。 我猜想起草 C++ 标准的人决定增加模仿者的复杂性不再合理(我不知道 C++ 库实现者在多大程度上利用了“漏洞” - 看起来 MS 可能正在收紧这一点,即使它在技术上不是必需的)。

我的一般建议是:

  • 文件应该#include它需要的内容。
  • 它不应该期望其他东西来#include它需要的东西。
  • 它不应该#include不需要的东西,因为其他东西可能需要它。

真正的测试是这样的:您应该能够编译包含任何单个#include的源文件,并且除了“没有main() ”之外不会出现错误或警告。 如果你通过了这个测试,那么你可以期待任何其他东西都能够#include你的文件而没有问题。 我编写了一个名为“hcheck”的简短脚本,我用它来测试它:

#!/usr/bin/env bash
# hcheck: Check header file syntax (works on source files, too...)
if [ $# -eq 0 ]; then
    echo "Usage: $0 <filename>"
    exit 1
fi

for f in "$@" ; do
    case $f in
        *.c | *.cpp | *.cc | *.h | *.hh | *.hpp )
            echo "#include \"$f\"" > hcheck.cc
            printf "\n\033[4mChecking $f\033[0m\n"
            make -s $hcheck.o
            rm -f hcheck.o hcheck.cc
            ;;
    esac
done

我确信这个脚本有几件事可以做得更好,但这应该是一个很好的起点。

如果这太多了,并且如果您的 header 文件几乎总是有相应的源文件,那么另一种技术是要求关联的 header 是源文件中的第一个#include 例如:

富.h:

#ifndef Foo_h
#define Foo_h

/* #includes that Foo.h needs go here. */

/* Other header declarations here */

#endif

Foo.c:

#include "Foo.h"
/* other #includes that Foo.c needs go here. */

/* source code here */

这也显示了其他人提到的 Foo.h 中的“包含守卫”。

通过将#include "Foo.h"放在首位, Foo.h必须#include其依赖项,否则会出现编译错误。

好吧, main 不应该首先依赖于stdio"foo.h" 包含两次并没有什么坏处。
另外,也许 foo。 h并不真正需要stdio 更有可能的是foo.c (实现)需要stdio

长话短说,我认为每个人都应该只包括他们需要的任何东西,并依靠包括警卫

一旦您进入具有数百或数千个 header 文件的项目,这将变得站不住脚。 假设我有一个名为"MyCoolFunction.h"的 header 文件,其中包含MyCoolFunction()的原型,并且 function 将指向结构的指针作为参数。 我应该能够假设包含MyCoolFunction.h将包含所有必要的内容,并允许我使用 function 而无需查看 .h 文件以查看我需要包含的其他内容。

如果 header 文件需要特定的 header,请将其添加到 header 文件中

#ifndef HEADER_GUARD_YOUR_STYLE
#define HEADER_GUARD_YOUR_STYLE

#include <stdio.h> /* FILE */
int foo(FILE *);

#endif /* HEADER GUARD */

如果代码文件不需要 header,则不要添加

/* #include <stdio.h> */ /* removed because unneeded */
#include <stddef.h> /* NULL */
#include "header.h"
int main(void) {
  foo(NULL);
  return 0;
}

为什么不在与 header 对应的 *.c 文件中#include 东西?

2 头文件包含在纯虚拟类中

如果我有一个像下面这样的纯虚拟类: 我有如下的类结构: 包含MyClassA / MyClassB的正确方法是什么? 我应该在接口类的头文件中进行一些前向声明,并将其真正包含在实现的头文件中,还是应该直接在接口类中包括MyClassA / B的头文件? ...

2012-02-15 09:17:12 2 134   c++
3 导入并包含在头文件中-什么时候可以?

我读过规则是不要#import或#include .h文件中的任何内容。 真的吗? 就在今天,我遇到了两次不得不做的单独的场合,一次是导入包含typedef enum的头文件,因为我的方法存根使用它作为参数,另一次是我必须导入头文件来声明委托。 这些情况的实际规则是什么? 有时可 ...

6 头文件应包含在.h或.m文件中吗?

如果我有四个.h / .m文件对 file1.h file2.h file3.h file4.h 我在file4中使用file1.h,file2.h和file3.h功能的地方,那些头文件应该包含在file4.h或file4.m中吗? ...

2011-04-21 19:20:40 3 527   xcode/ ios
8 头文件可以包含在多个源文件中,而没有重复保护

大多数头文件将其内容包装为: 如果将其删除,则将头文件包含在多个源文件中时是否会引起问题? 还是预处理器足够聪明,可以忽略它? (我知道在同一源文件中多次包含它时会引起问题) ...

2019-02-19 01:55:33 3 63   c++/ c
9 为什么头文件需要包含在定义文件中?

我是 C 新手,只是一个关于头文件的问题,下面是推荐使用头文件的代码: 我不明白为什么我们需要将#include "test.h"放在test.c文件中,这样做有什么好处? ...

2020-08-25 00:19:50 1 39   c/ gcc
10 使用头文件而不包含在源文件中

我将现有的borland c ++源代码移植到gcc Compatible中。 我正在使用make来编译源代码。 在borland源文件中的一个文件中,他使用的是来自不同头文件的定义,而没有将该头文件包括在特定的.h文件中。 当我尝试编译相同文件时,出现错误,提示未定义。 那么我们如何才 ...

暂无
暂无

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

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