繁体   English   中英

什么时候需要在c ++中使用#include

[英]When do you need to use #include in c++

我现在已经编程了一段时间,我还有一件事我还没想到,正是你需要#include东西。 我知道你可以安全地使用另一个文件中声明的东西。 但有时我发现我可以删除一个#include ,一切都会编译得很好。 据我所知,这是因为已经包含的其他文件包括外部定义。 有两种特殊情况我有兴趣了解以下行为:

  1. 假设我们有三个.h / .cc对:f1.h / .cc,f2.h / .cc和f3.h / .cc。 如果f2.h / .cc包含f1.h且f3.h / .cc包含f2.h,则f3.h / .cc必须包含f1.h或者所有f1.h的定义都可见f3文件包含在f2中?

  2. 再次说我们有三个.h / .cc对:f1.h / .cc,f2.h / .cc和f3.h / .cc。 如果f2包括f1并且f2包括f1然后f3包括f1或f2,那么f1和f2之间的“循环连接”会引起问题吗?

您是否了解我可以阅读的任何在线资源,以便更好地了解在一个文件中包含某些内容会如何影响项目中的后续文件?

没什么可说的。 如果你使用某些东西,你必须包括声明你使用的东西的标题。 关于唯一的例外是前向声明类/结构或方法,如:

class myclass;   

如果你只需要声明一个指针或类的引用。

您不能真正依赖其他标题,包括您需要的标题。 任何一天,其他标题的维护者都会意识到他/她不再需要包含它并将其删除。

问题1:我认为你所缺少的是“f2包括f1”和“f2 保证包含f1”之间的区别。 这对于标准标头尤为重要,因为任何标准标头都允许包含任何其他标头。 因此,如果您依赖于在您的机器上工作的间接包含,那么您的代码可能无法在不同的C ++实现上进行编译。

如果你有一个库,其中“f2.h”的文档说明或暗示它包含“f1.h”,这意味着它将始终存在于所有兼容版本中,因此你可以依赖间接包含。 您可以在使用库的一个组件的情况下执行此操作,该组件基本上依赖于该库的另一个组件,但其他组件可能被其他用户隔离使用。 对于一个假设的例子,“xhtml_parser.h”可能合理地证明它提供了来自“xml_parser.h”的所有定义,以及一些额外的定义。

问题2:嗯,你想改一下这个问题吗? “f2包括f1,f2包括f1”不是你的意思,也没有“循环链接”。 如果您编写标题使得f1包含f2而f2包含f1,则可能会导致问题,因为include不是“链接”,它几乎是对另一个头文件内容的剪切和粘贴。

因此,即使在f3进入图片之前,循环包含也可能存在问题:

f1.h
----
#ifndef f1_h_included
#define f1_h_included

#include "f2.h"
struct DerivedA : BaseA {};
struct BaseB {};

#endif

f2.h
----
#ifndef f2_h_included
#define f2_h_included

#include "f1.h"
struct BaseA {};
struct DerivedB : BaseB {};

#endif

无论你包括哪个“f1.h”和“f2.h”,这都不会编译。 假设首先包含f1,预处理后的结果如下所示:

// contents of f2.h, pasted in at line 4 of f1.h
// (contents of f1.h on the circular include are ignored due to include guard)
struct BaseA {};
struct DerivedB : BaseB {};

// rest of f1.h
struct DerivedA : BaseA {};
struct BaseB {};

因此DerivedB指定了尚未定义的基类。 反过来包括它们,与DerivedA相同的问题。

你已经把它钉了很多。 为了使用输入/输出流,我需要包含头文件。 如果您编写了支持大整数类型的bigint类,并将此类发送给了朋友。 你的朋友需要在他的程序中包含它才能使用它。 因此,当您的程序无法使用时,请包含一些内容。

但有时我发现我可以删除一个#include,一切都会编译得很好。 据我所知,这是因为已经包含的其他文件包括外部定义。

正确。 这只是因为运气而已。

假设我们有三个.h / .cc对:f1.h / .cc,f2.h / .cc和f3.h / .cc。 如果f2.h / .cc包含f1.h且f3.h / .cc包含f2.h,则f3.h / .cc必须包含f1.h或者所有f1.h的定义都可见f3文件包含在f2中?

你可能意味着f1.h的声明 ,而不是定义 ,尽管你可能有一些类和模板函数定义。

无论如何,答案是否定的,它永远不会是必要的。 这些声明将是可见的。 预处理程序指令只是简单的文本插入。 一旦你想到了你的头脑,扩展变得容易理解。

再次说我们有三个.h / .cc对:f1.h / .cc,f2.h / .cc和f3.h / .cc。 如果f2包括f1并且f2包括f1然后f3包括f1或f2,那么f1和f2之间的“循环连接”会引起问题吗?

是的,可能。 如果头文件的内容是健全的,则头部保护可以缓解此问题。 但是如果f2的内容依赖于f1的内容 ,反之亦然,那么你在代码中就会有一个循环依赖。 这应该通过使用 前向声明删除循环依赖项来解决。

您是否了解我可以阅读的任何在线资源,以便更好地了解在一个文件中包含某些内容会如何影响项目中的后续文件?

我可以推荐这些资源

首先是简短的答案,解释如下:

1)不需要在f3.h / .cc中声明#include“f1.h”,因为这会产生包含周期(不应该这样做)

2)在1-> 2,1-> 2-> 3中没有循环,如果你使用包含守卫,即使只包含2个 (#ifndef 2 #define 2 my2code #endif)

实现是特定于编译器的,但通常是:在菱形包含中,良好的编译器将展平包含路径并在最深层找到文件,该文件包含在某处但不需要包含任何其他内容。 然后它将不断包含那些包含的文件,并且仅依赖于已包含的文件。 由于这可能会导致重复包含,因此您应始终只包含标题(.cc将从相同的目录链接而不显式包含),并使用包含保护来保护您的标题文件:

例如myheader.h:

#ifndef _myheader_h_
#define _myheader_h_
int myglobal;
#endif

如果你在包含中有一个循环,它取决于编译器:它要么试图找到最深层次要么失败要么选择,要么它不试图选择最深层次并包括你给出的顺序你的文件; 无论如何:如果你避免循环(你应该)并且使用包含防护,那么你就是安全的。

暂无
暂无

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

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