如何正确使用#include指令?

时间:2009-01-21 09:22:41

标签: c++ c

是否有关于如何正确使用#include的材料? 我没有找到任何详细解释这种用法的C / C ++教科书。 在正式项目中,我总是对处理它感到困惑。

10 个答案:

答案 0 :(得分:20)

总是让我失望的最重要的是:

这将在标题路径中搜索:

#include <stdio.h>

在您的本地目录中搜索:

#include "myfile.h"

你应该对每个标题做的第二件事是:

myfilename.h:

#ifndef MYFILENAME_H
#define MYFILENAME_H
//put code here
#endif

这种模式意味着你不能在编辑中重新定义标题(干杯到orsogufo指向我,这被称为“包含守卫”)。做一些关于C编译器如何实际编译文件(链接之前)的阅读,因为这将使#define和#include的世界对你有很大意义,C语言编译器解析文本时不是很智能。 (然而,C编译器本身是另一回事)

答案 1 :(得分:14)

  • 如果你有钱,请检查John Lakos的大规模C ++软件设计。
  • Google C ++编码指南也有一些不错的东西。
  • 也可以在线查看Sutter Herb材料(博客)。

基本上你需要了解哪些包含标题不是必需的,例如。前瞻性声明还要尝试确保包含文件逐个编译,并且只在必须时将#includes放在h文件中(例如模板)。

答案 2 :(得分:11)

因此,您的编译器可能支持包含文件的2个唯一搜索路径:
非正式地,我们可以调用系统包括路径和用户包含路径 #include&lt; XX&gt; 搜索系统包含路径 #include“XX”搜索用户包含路径,然后系统包含路径。

检查标准草案n2521:
第16.2节:

2 A preprocessing directive of the form 

  # include < h-char-sequence> new-line 

  searches a sequence of implementation-defined places for a header identified
  uniquely by the specified sequence between the < and > delimiters, and
  causes the replacement of that directive by the entire contents of the
  header. How the places are specified or the header identified is
  implementation-defined. 

3 A preprocessing directive of the form 

  # include " q-char-sequence" new-line 

  causes the replacement of that directive by the entire contents of the
  source file identified by the specified sequence between the " " delimiters.
  The named source file is searched for in an implementation-defined manner.
  If this search is not supported, or if the search fails, the directive is
  reprocessed as if it read

  # include < h-char-sequence> new-line 

  with the identical contained sequence (including > characters, if any)
  from the original directive. 

这样做的一个例子是gcc

  -isystem <dir>              Add <dir> to the start of the system include path
  -idirafter <dir>            Add <dir> to the end of the system include path
  -iwithprefix <dir>          Add <dir> to the end of the system include path
  -iquote <dir>               Add <dir> to the end of the quote include path
  -iwithprefixbefore <dir>    Add <dir> to the end of the main include path
  -I <dir>                    Add <dir> to the end of the main include path

要查看您的gcc搜索的位置,请执行以下操作:

g++ -v -E -xc++ /dev/null -I LOOK_IN_HERE
#include "..." search starts here:
#include <...> search starts here:
  LOOK_IN_HERE
  /usr/include/c++/4.0.0
  /usr/include/c++/4.0.0/i686-apple-darwin9
  /usr/include/c++/4.0.0/backward
  /usr/local/include
  /usr/lib/gcc/i686-apple-darwin9/4.0.1/include
  /usr/include
  /System/Library/Frameworks (framework directory)
  /Library/Frameworks (framework directory)
End of search list.

那么你如何使用这些知识呢 有几种思想流派。但我总是列出我的库,从最具体到最常见。

实施例

文件:plop.cpp

#include "plop.h"
#include "plop-used-class.h"

/// C Header Files
#include <stdio.h>    // I know bad example but I drew a blank

/// C++ Header files
#include <vector>
#include <memory>

这样,如果头文件“plop-used-class.h”应该包含&lt; vector&gt;这将由编译器来解决。如果我把&lt; vector&gt;在顶部,此错误将在编译器中隐藏。

答案 3 :(得分:3)

除了其他注释之外,请记住,如果只有指针或引用,则不需要#include另一个头中的头。 E.g:

需要标题:

#include "Y.h"
class X
{
   Y y; // need header for Y
};

不需要标头:

class Y; 
class X
{
   Y* y; // don't need header for Y
};
//#include "Y.h" in .cpp file

第二个示例编译速度更快,依赖性更低。这在大型代码库中很重要。

答案 4 :(得分:2)

头文件是C分离接口和实现的方式。它们分为两种类型:标准和用户定义的头文件。 标准头文件(如string.h)允许我们访问底层C库的功能。您应该在每个使用相关功能的.c文件中#include它。通常这会在#include中使用括号 用户定义的头文件将您的函数实现暴露给其他程序员或C代码的其他部分。如果你已经实现了一个名为rational.c的模块用于有理数的计算,那么它的公共接口应该有一个相应的rational.h文件。使用该功能的每个文件都应该#include rational.h,而rational.c应该#include它。通常这是使用#include“rational.h”完成的。 编译#includes的部分称为C preprocessor。它主要是文本替换和粘贴文本。 斯宾塞在他的模式中是正确的,以防止重复#includes,这会搞乱命名空间。这是包容的基础,GNU Make给你更多的力量,也有更多的麻烦。

答案 5 :(得分:2)

只是Andy Brice答案的附录,你也可以使用函数返回值的前向声明:

class Question;
class Answer;

class UniversityChallenge
{
...
    Answer AskQuestion( Question* );
...
};

以下是我前一段时间回答一些问题的问题的链接http://bytes.com/groups/c/606466-forward-declaration-allowed

答案 6 :(得分:0)

使用#include<filename.h>查看the discussion#include<filename> for C ++包括C库。

答案 7 :(得分:0)

<块引用>

有没有关于如何正确使用#include 的资料?

我强烈推荐 SF: Source filesC++ Core Guidelines 部分作为一个好的起点。

<块引用>

我没有找到任何详细解释这种用法的 C/C++ 教科书。

"Large-Scale C++ Software Design" by John Lakos 中可以找到许多关于 C++ 项目物理组合主题的传统智慧。

<块引用>

在正式项目中,我总是在处理它时感到困惑。

你们相处得很好。在 C++20 modules 之前,#include 是从多个文件组合 C++ 翻译单元的唯一实用方法。这是一个简单的、有限的工具,预处理器通过它基本上可以将整个文件复制/粘贴到其他文件中。由此产生的编译器输入通常是巨大的,并且工作通常会从一个翻译单元重复到下一个。

答案 8 :(得分:-1)

如果#include "yourfile.h"位于当前工作目录中,则使用yourfile.h#include <yourfile.h>如果yourfile.h文件的路径包含在C ++ include目录中(在配置中的某处,例如:c:\mylib\yourfile.h,则必须将路径c:\mylib\指定为包含目录) 您还可以包括.cpp和.hpp(h plus plus)。 有一组特定的文件可以写成:#include <iostream>。对于特定的示例工作,您需要指定using namespace std;

有一个非常好的软件与microsoft的visual c ++集成,并显示包含路径。 http://www.profactor.co.uk/includemanager.php

答案 9 :(得分:-1)

编辑:Andy Brice也以更简洁的方式提出了这一点。

在null的答案中跟进,最重要的考虑因素是你把你的#include放在哪里。

当您编写#include时,预处理器字面上包含您在当前文件中列出的文件的内容,包括那些文件中的任何#include。这显然会在编译时导致非常大的文件(coad膨胀),所以你需要仔细考虑是否需要#include。

在一个标准的代码文件布局中,你有一个带有类和函数声明的类的.h文件,然后是.cpp实现文件,你应该注意标题中的#includes数量文件。这是因为,每次更改头文件时,任何包含它的文件(即使用您的类的文件)也必须重新编译;如果头部本身有很多包含,那么使用该类的每个文件在编译时都会显着膨胀。

最好在可能的情况下使用前向声明,以便您可以编写方法签名等,然后#include .cpp文件中的相关文件,以便您可以实际使用代码所依赖的类和结构上。

//In myclass.h
class UtilClass; //Forward declaration of UtilClass - avoids having to #include untilclass.h here

class MyClass
{
    MyClass();
    ~MyClass();

    void DoSomethingWithUtils(UtilClass *util); //This will compile due to forward declaration above
};

//Then in the .cpp
#include utilclass.h

void MyClass::DoSomethingWithUtils(UtilClass *util)
{
    util->DoSomething(); //This will compile, because the class definition is included locally in this .cpp file.
}