【问题标题】:How to include header files如何包含头文件
【发布时间】:2015-06-18 13:53:08
【问题描述】:

我如何导入头文件重要吗?我见过双引号和使用的箭头。

#include <stdlib.h>
#include "Some_Header.h"

它们是否也以某种方式大写有关系吗?对此进行试验,似乎无关紧要,但我认为教程这样做一定有原因。

另一个问题是,(来自这里的 Java),我如何访问定义它的文件之外的类?说,我有一个.cpp 和两个.cpp。

在一个.cpp中:

class Something {
    ...

在两个.cpp中:

class SomethingElse {
    Something *example;
    ...

这样吗?在 Java 中,您只需在类名前加上“public”即可。在 C++ 中,争吵类似乎有点困难..

【问题讨论】:

  • @GMan:他从未说过 Java 是 C++,或者 C++ 是 Java。他只是解释了他在 Java 中的习惯,并想知道 C++ 中的等价物是什么。
  • @GMan:对于学习新 X 的人来说,尝试找到与他们使用过的以前 X 的等价物是很自然的。是的,在这种情况下可以说没有直接等价,但是 Java 中还有许多其他的东西在 C++ 中确实有等价。例如:如果他问“在 Java 中我写 boolean x,我如何在 C++ 中做到这一点”,你会给他一个类似的“Java 不是 C++”的答案,还是让他知道“布尔”是拼写的C ++中的“布尔”?我认为你对人们用 Y 语言编程 X 的担忧是有道理的,但我认为你在这里过火了。
  • @GMan:建议他读一本书不是问题。问题在于您的“说真的,Java 不是 C++”评论所表达的态度。关于 SO 的大部分问题都是基本问题,可以通过阅读正确的书籍或执行 Google 搜索来回答,但这并不意味着它们应该被粗鲁地对待。我怀疑出于某种原因,提到 Java 让您感到不安。克服它。
  • @fredoverflow 您的链接非常有用,并回答了我的许多 C++ 构建问题。谢谢!

标签: c++ header-files


【解决方案1】:

#include 指令中的尖括号表示搜索路径仅限于“系统”包含目录。双引号表示搜索路径包含当前目录,后跟系统包含目录。

当您的操作系统使用区分大小写的文件系统时,文件名的大小写很重要。听起来您可能使用的是 Windows 或 Mac OS X,默认情况下文件名不区分大小写。

【讨论】:

    【解决方案2】:

    尖括号在系统头文件目录中查找头文件(例如/usr/include)。 Quotes 只是一个绝对或相对路径名,例如/path/to/header.h../headers/abc.h

    要从其他文件访问类,只需#include 与该类的其他文件。请务必对您的程序进行结构化,以确保不会多次包含任何文件。

    【讨论】:

    • "确保您的程序结构不会被多次包含。" -> 只要你使用 include 保护,你就可以尽可能频繁地包含它们,这是你应该的。
    • 请注意,类声明应该放在标题中,而不是 .cpp 中。你不应该#include a .cpp。
    • 头文件和源文件没有技术上的区别;如何使用它们取决于开发人员。这都是一个微不足道的文件扩展名。
    • 好吧,毕竟所有文件都是八位字节流,让我们删除扩展名和所有元数据,谁在乎呢?由用户决定如何打开它们... <_>
    • 你没有抓住重点;我是说扩展名是作为如何使用文件的指示,给头文件一个 .cpp 扩展名至少是令人困惑的,对于程序员(他们会很困惑)和 IDE(他们会尝试编译它自己)。
    【解决方案3】:

    首先是一个简单的问题:

    它们是否也以某种方式大写有关系吗?

    在大多数情况下,includes 指的是文件,编译器应该能够找到您包含在系统中的文件。因此,在文件系统区分大小写的所有系统中,大写很重要。如果您想保持最低限度的可移植性,您应该在文件名和include 上保持一致。 (所有linux 和mac os默认都有区分大小写的文件系统,在windows中你可以配置NTFS也区分大小写)

    现在,文件的命名方式真的很重要吗?不,它不会,只要你在包含的内容上是一致的。另请注意,建议遵循某种模式以简化包含。

    我如何导入头文件重要吗?

    这个标准目前还不是很清楚,不同的实现遵循不同的路径。该标准定义它们可能不同,因为编译器搜索包含文件的位置和顺序集是实现定义的,并且如果包含带有尖括号或双引号,则它们可能会有所不同。如果使用引号包含无法定位文件,则编译器必须回退以处理包含,就好像它是用尖括号编写的一样。

    #include <x.h> // search in order in set1 of directories
    #include "x.h" // search in order in set2 of directories
                   // if search fails, search also in set1
    

    这意味着如果文件仅存在于 set1 中,则两种类型的包含都会找到它。如果文件存在于 set2 但不存在于 set1 中,则仅引用包含将找到它。如果 set1 和 set2 中存在同名的不同文件,则每种包含类型都会找到并包含不同的文件。如果 set1 和 set2 的公共子集中存在两个同名文件,但集合的顺序不同,则每个包含类型可以定位到不同的文件。

    回到现实世界,大多数编译器只会包含 set2 中的当前目录,而 set1 是所有系统包含位置(通常可以使用编译器参数扩展)在这些情况下,如果文件只存在于当前目录,#include "a.h" 会找到它,但#include &lt;a.h&gt; 不会。

    现在,无论这是否是常见行为,都有一些 隐含 语义在 C/C++ 中是惯用的。一般方括号用于包含系统头文件和外部头文件,而双引号用于包含本地文件。同一项目中的库应被视为 local 还是 external 存在一个灰色地带。也就是说,即使总是包含双引号也可以,大多数人会使用角引号来引用不属于当前模块的标题。

    最后,虽然我所知道的编译器都没有这样做,但该标准允许实现(编译器)不将标准头文件作为真实文件生成,而是在内部处理标准头文件的包含。这是理论上#include "vector" 可能无法包含std::vector 类(或任何其他标准标头)的定义的唯一情况。但这不是一个实际问题,而且我认为永远不会。

    【讨论】:

    • 默认的 Mac OS X 文件系统不区分大小写。
    • 那一定是我弄的区分大小写的:)...安装系统已经两年多了。
    【解决方案4】:

    问题 1

    我如何导入标题是否重要 文件? 它们是否大写有关系吗 也有某种方式?

    没关系,但通常的做法是,

    • 对系统使用尖括号 标题。
    • 用户的用户双引号 定义的标头(您自己的标头)

    问题 2 和 3

    另一个问题是,(来自Java 在这里),我如何访问外面的课程 它是在哪个文件中定义的?

    您需要将类定义放在头文件中,并将该头文件包含在您要使用该类的任何位置。 对于您的情况,如下所示。

    //One.h
    #ifndef ONE_H
    #define ONE_H
    class Something
    {
    public:
        void doSomething(){}
    
    };
    #endif
    
    //Two.cpp
    #include "One.h"
    class SomethingElse
    {
       SomeThing *example;
    };
    

    【讨论】:

    • class Something { /* ... */ }; 实际上是一个类定义,而不是一个类声明。类声明看起来像class Something;(注意缺少的类主体),并且经常被冗余地称为前向声明
    • 我认为文件名的大小写在 Linux 等系统上很重要,因为它们区分大小写。在 Windows 上没关系,文件名只保留大小写。
    • 您将他的第二个问题引用为“问题 1”,回答了他实际的第一个问题,然后转到他的第三个问题(称为“问题 2”)
    • “没关系,但通常的做法是” - 实际上,它确实很重要,AFAIK 编译器应该搜索系统/编译器标头中包含括号的标头路径,以及包含在当前文件路径中的引号(或者,至少,它首先尝试)。
    • 你不应该在包含保护名称前加上_;这样的名字是保留的。
    【解决方案5】:

    首先,#include 是 C 预处理器指令,严格来说不是 C++ 语言的一部分。您可以在here 找到更多相关信息,尽管这是专门针对 GNU C 预处理器的,因此可能与您使用的有所不同。我认为您应该始终在包含文件中假设区分大小写。不这样做可能会使您的代码难以移植到区分大小写的操作系统,例如 UNIX。

    如上所述,"" 或 的使用相当微妙,大多数时候您不会注意到任何区别。使用“”一般先搜索当前目录。我倾向于不将其用作:

    • 我知道我的头文件在哪里 - 我总是在编译行用-I 指定它们。
    • 以前,我曾在本地复制的标头副本覆盖了我希望获取的中心副本时被发现。

    我还注意到一些副作用,例如使用 make 创建依赖树时(我不太记得这个问题 - 它确实以不同的方式处理不同的包含,遵循一些而不是其他的,但这大约是 7 年以前)

    其次,您关于如何在其他文件中引用函数的问题得到解答here/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-01
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 2019-08-04
      • 2012-10-05
      • 2017-06-13
      相关资源
      最近更新 更多