在多个文件中使用#include <iostream>

6

我希望这个问题在这个网站上之前没有被问过。我无法从谷歌中找到一个确切的答案。

当您在项目的多个文件中使用 #include iostream 时会发生什么?我总是在我的头文件中使用 #ifndef 和 #define。那是否可以防止 iostream 被包含多次?


2
是的,这种技术可以防止多重包含,并被称为包含保护 - Alexander Shukaev
3
唯一真正的危险就是它在同一个翻译单元中被包含了多次,这里指的是标准头文件已经有了包含保护机制。请注意,这里说的是“翻译单元”而不是“项目”。 - chris
那么,如果我正在使用继承,将iostream仅包含在基类中是一个好主意吗?由于派生类都依赖于基类,这应该保证它只被包含一次,对吗? - Shan
@Shan,这主要是个人喜好的问题。我看到很多人喜欢在头文件中包含一些被该头文件源代码所包含的内容,而其他人(包括我)则会直接在每个使用它的文件中包含所有直接使用的头文件。请记住,如果您可以使用前向声明或实际上不在头文件中使用它,则不必始终在头文件中包含内容。 - chris
@chris 很好,非常感谢你的帮助。这是一项课程作业,我只是想确保不会因为多个 #includes 而被扣分。 - Shan
相关问题,我也在想同样的事情。 - jjepsuomi
4个回答

6

我对这个问题有两种解释:

  1. 在同一个编译单元中可以多次包含iostream吗?
    • 是的,可以安全地这样做。所有标准头文件都有 include guards,因此允许安全使用。
  2. 如果在代码中自己使用include guards是否会防止多次包含iostream
    • 当然会,它也将防止位于#ifndef#endif之间(或者在使用#pragma once标记的头文件中,在支持它的编译器中)的任何内容被编译器看到超过一次…… 这就是 include guards 的作用,对吧?但是对于#include <iostream>来说,这并不是必需的,因为它已经受到了多重包含的保护。

3
像chris和Haroogan所说的那样,是的他们会防止这种情况发生。 #ifndef和#define是预处理器指令,它们被翻译成英文为: #ifndef(如果未定义) #define(定义) 因此,如果您创建了一个标头文件,并且两次#include "myheader.h",则该文件不会再次被包含,因为您将其包含在if语句中,这将导致文件仅在尚未包含(定义)时被包含(定义)。

但是标准头文件有内置的保护措施吗? - Shan
@Shan,我无法想象它们在某种意义上会比其他标头更特殊。与规则“所有标准标头必须防止多次包含”相比,这听起来是一个非常不必要的添加到标准中。 - chris

0
#ifndef __IOSTREAM_H
#include <iostream>
#endif

...

似乎大多数标准头文件都有像上面那样的包含保护。

或者,您可以通过定义所需的宏来创建自己的包含保护。


0

无论如何,即使你使用了ifndef,你仍然尝试多次包含它。因为多个文件只会被包含一次。并且所有的尝试都是为了包含<iostream>,但如果你打开<iostream>,它就有了。

#pragma once

这基本上意味着它只会被包含一次。在业界中,我发现这并不是避免多次包含的建议方式,因为很难知道它不会再次被包含,而与在顶部和底部看到ifndef相比。

1
没有必要这样做,因为#pragma once是非标准的。 - chris
我打赌主要原因是可移植性。 - Alexander Shukaev
你的意思是它不需要吗?我打开文件检查了一下它使用了什么类型的包含保护,结果发现它使用了 #pragma once - Zanven
@Zanven,不必意味着不能。我想说的是,标准中没有提到#pragma once,因此它不可能强制要求在标准头文件中使用它。我找不到相关内容,但我想它肯定有规定实现必须保护标准头文件免受多次包含的影响,而如何实现则取决于实现者,如果实现支持,#pragma once就是一种可能性。 - chris
是的,我同意#pragma once不是一个好的做法。这是直接从维基百科上得到的。#pragma once是一种非标准但被广泛支持的预处理器指令,旨在使当前源文件在单个编译中仅被包含一次。因此,#pragma once具有与#include保护相同的目的,但具有几个优点,包括:更少的代码、避免名称冲突,有时可以提高编译速度。 - Zanven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接