提示:本站收集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 吗?
你已经概述了关于这个主题的两种主要哲学。
我自己的观点(我认为这就是人们真正可以拥有的全部)是标题应该尽可能独立。 我不想为了能够使用 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 库的实现者的复杂性。 他们必须跳过一些障碍才能做到这一点(特别是为了支持可以通过多个标头中的任何一个引入的定义,例如NULL
或size_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 东西?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.