C++ C++;是否包含包含的头文件包含的所有头文件?

C++ C++;是否包含包含的头文件包含的所有头文件?,c++,header-files,C++,Header Files,在这个示例代码中,我有3个文件: testHeader.h: void hello() { } 文件1.h: #include "testHeader.h" #include <iostream> void sayHi() { std::cout << "hi" << std::endl; } #包括“testHeader.h” #包括 void sayHi(){std::cout除非受到预处理器守卫的奇怪保护,

在这个示例代码中,我有3个文件:

testHeader.h:

void hello() {  }
文件1.h:

#include "testHeader.h"
#include <iostream>
void sayHi() { std::cout << "hi" << std::endl; }
#包括“testHeader.h”
#包括

void sayHi(){std::cout除非受到预处理器守卫的奇怪保护,否则是的,你会得到它们。
#include
在很大程度上是一种预处理器技巧,大致相当于将include的文本转储到源代码中,并且是可传递的;如果你
#include
,你会得到
a.h
的扩展形式,包括预处理器它的所有包含的扩展形式,它们的所有包含,等等,无限,在一次传递中

请注意,明确地包含您直接依赖的所有内容仍然是一个好主意;当然,其他
.h
文件今天可能包含
#include
,但如果它们不是公开的API的必要部分,则不能保证下一版本会包含它们


还值得注意的是,预处理器include guard(和/或
#pragma once
)几乎普遍用于表示
.h
文件的内容不会被包含两次(按照惯例,这不是保证;如果
.h
文件写得不好,或者设计用于多个包含且具有不同预处理器设置的怪异文件,则不会遵守)在
.cpp
中重新包含一个标头几乎没有成本,因为它已经从您包含的
.h
中获得了标头。在较旧的编译器上,如果没有
#pragma once
并且没有对include-guard进行特殊处理,它可能需要再次加载标头,查看该标头,然后在第二个include上不转储任何内容;许多wer编译器足够聪明,甚至可以避免这种成本。关键是,不要试图通过避免冗余的
#include
s来优化;每个文件都应该有一套完整的
#include
s,用于该文件中使用的内容,不能多,也不能少。

如果您在旧的编译器上工作,没有一次pragma,那么请尝试执行以下操作

---文件1.h---

\ifndef文件1\u H
#定义文件1_H
#包括“testHeader.h”
#包括
void sayHi();
#恩迪夫
---file1.cpp---

#包括“file.h”

void sayHi(){std::cout-Yes,当然。
#include
字面上是ctrl-v。如果include形成循环,并且头之间存在循环依赖关系,则可能会遇到问题,但这偏离了主题。但是,让每个头都能自给自足是一个好做法。您不希望头中的更改会随机打断其他一些可能不重要的头r使用了头。一个好的经验法则是,如果可以避免,使用前向声明而不是包含其他头。无论如何,应该使用一次pragma或头保护(
\ifndef
对),这是标准库标题可以完成的。在标题中放置定义可能会导致中断。有关避免此问题的帮助,请参阅和。可能值得注意的是,所有这些都发生在一次传递中(如果您的描述还不够清楚)。@πάνταῥεῖ: 当然。我不确定这对OP的案子是否真的重要,但很高兴知道。
#include "file1.h"
void sayHello() { std::cout << "hello" << std::endl; }
#ifndef FILE1_H
#define FILE1_H

#include "testHeader.h"
#include <iostream>
void sayHi();

#endif
#include "file.h"
void sayHi() { std::cout << "hi" << std::endl; }
#ifndef FILE2_H
#define FILE2_H

#include "file1.h"
#include <iostream>
void sayHello();

#endif