应该将“include”放在C ++中

时间:2010-02-19 15:51:16

标签: c++ include

我正在阅读一些c ++代码并注意头文件和.cpp文件中都有“#include”。我想如果我移动文件中的所有“#include”,让我们说foo.cpp,它的'头文件foo.hh,让foo.cpp只包含foo.hh代码应该工作,无论如何不考虑像缺点,效率等。

我知道我的“突然”想法必定在某种程度上是一个坏主意,但它的确切缺点是什么?我是c ++的新手,所以在我自己回答这个问题之前,我不想阅读很多C ++书。所以请在这里提出问题以寻求帮助。提前谢谢。

9 个答案:

答案 0 :(得分:32)

通常情况下,尽可能将包含放在.cpp文件中,并且只有在.h文件中才能使用。

在许多情况下,您可以使用forward declarations来删除包含其他标头的标头的需要:这有助于减少编译时间,这可能会随着项目的增长而成为一个大问题。这是一个很好的习惯,因为尝试在以后解决它(当它已经是一个问题)可能是一个完整的噩梦。

此规则的例外是模板化类(或函数):为了使用它们,您需要查看完整定义,这通常意味着将它们放在头文件中。

答案 1 :(得分:13)

标头中的包含文件应该只是支持该标头所必需的文件。例如,如果标题声明了一个向量,则应该包含向量,但没有理由包含字符串。您应该能够拥有一个只包含该单个头文件的空程序并进行编译。

在源代码中,您需要包含所有调用的内容,当然。如果你的标题都不需要iostream,但你需要它来实际来源,它应该单独包含。

在我看来,包含文件污染是代码腐烂最糟糕的形式之一。

编辑:嘿。看起来解析器吃了>和<符号。

答案 2 :(得分:5)

您还可以将包含头文件在内的所有其他文件传递给您的标题中的所有#include

在C ++中(如在C中)#include由预处理器处理,只需在#include d文件中插入所有文本代替#include语句即可。因此,对于大量#include s,您可以将可编译文件的大小夸大到数百KB - 并且编译器需要为每个文件解析所有这些。请注意,必须在#include d的每个位置再次重新分析包含在不同位置的同一文件!这可以减慢编译速度。

如果您需要在标头中声明(但未定义)内容,请使用forward declaration代替#include s。

答案 3 :(得分:1)

如果你#include .cpp文件,你可能会从链接器中得到大量“多重定义”错误。理论上,您可以将所有内容整合到一个翻译单元中,但这也意味着每次对单个文件进行更改时都必须重新构建所有内容。对于真实世界的项目来说,这是不可接受的,这就是我们拥有像make这样的连接器和工具的原因。

答案 4 :(得分:1)

包含头文件中的头文件很好,因此包含在c ++文件中,但是,为了最小化构建时间,通常最好避免在另一个头中包含头文件,除非绝对必要,特别是如果许多c ++文件包含相同的标题。

答案 5 :(得分:1)

.hh(或.h)文件应该用于声明。

.cpp(或.cc)文件应该用于定义和实现。

首先要意识到#include语句是 literal #include "foo.h"从字面上复制foo.h的内容并将其粘贴到include指令所在的另一个文件中。

这个想法是bar.cpp和baz.cpp等其他一些文件可能想要使用foo.cc中存在的一些代码。这样做的方法通常是bar.cpp和baz.cpp到#include "foo.h"来获取他们想要使用的函数或类的声明,然后在链接时,链接器会挂钩这些在bar.cpp和baz.cpp中用于foo.cpp中的实现(这是链接器的全部要点)。

如果你把所有东西放在foo.h中并尝试这样做,你就会遇到问题。假设foo.h声明了一个名为doFoo()的函数。如果这个函数的定义(代码)在foo.cc中,那很好。但是如果将doFoo()的代码移到foo.h中,然后在foo.cpp,bar.cpp和baz.cpp中包含foo.h,那么现在有一个名为{{1}的函数的三个定义并且你的链接器会抱怨,因为你不允许在同一范围内有多个同名的东西。

答案 6 :(得分:1)

在头文件中使用#include没有任何问题。这是一种非常常见的做法,您不希望给用户增加负担,同时还要记住需要的其他模糊标题。

标准示例是#include <vector>。获取矢量类。以及正确编译向量类所需的大量内部CRT头文件,这些内容实际上是您不需要也不想知道的。

答案 7 :(得分:1)

虽然头文件应仅包含它所需的内容,但“它需要的内容”比您想象的更流畅,并且取决于您放置标头的目的。我的意思是,有些标题实际上是库或其他代码的接口文档。在这些情况下,标题必须包含(并且可能是#include)其他开发人员为了正确使用您的库而需要的所有内容。

答案 8 :(得分:0)

如果使用“include guards”,则可以避免多个定义错误。

(begin myheader.h)
#ifndef _myheader_h_
#define _myheader_h_
struct blah {};
extern int whatsit;
#endif //_myheader_h_

现在如果你在其他头文件中#include“myheader.h”,它只会被包含一次(由于定义了_myheader_h_)。我相信MSVC有一个“#pragma once”具有相同的功能。