【问题标题】:The difference between ways of including files in C++C++中包含文件方式的区别
【发布时间】:2013-06-26 20:49:23
【问题描述】:

每当我问如何在我的 C++ 项目中添加类或库时,每个人都说我应该创建一个 .h 文件,使用预处理器指令,在其中声明函数原型,并创建一个新的 .cpp 文件以记录下来其中的函数,最后将 .h 文件包含在我们的 main.cpp 中。 但是当我简单地将 cpp/h 添加到我的源文件时,它也可以正常工作。那么如果我可以将所有代码写入一个文件并将其包含在我的 main.cpp 中,那么创建 .cpp 和 .h 有什么意义呢?

【问题讨论】:

  • 简单来说,更好的代码管理。
  • 您是否尝试过事先找到任何以前的答案? read me
  • 随着代码的增长,你会明白为什么,年轻的蚱蜢。
  • @molbdnilo 如果你知道答案请写出来,如果你不知道请不要写无意义的东西

标签: c++ header include


【解决方案1】:

这可能会导致两种截然不同的问题。

首先,它会导致构建时间过长。当您将 .cpp 文件分开时,您可以在更改该文件时编译该文件,否则只需将链接器链接到该文件中的函数,而无需每次都重新编译。只要您的项目很小,每次重新编译所有代码都不是什么大问题,但如果项目变得非常大,很快就会变得很麻烦。

第二个问题是同一函数的多个定义。例如假设您在 A.cpp 中定义了一些函数,并且您需要在 B.cpp 和 C.cpp 中使用这些函数。如果你直接在 B.cpp 和 C.cpp 中包含那些函数(而不仅仅是声明)的源代码,然后尝试将 B 和 C 链接在一起,你在 A.cpp 中对所有函数都有多个定义。导致未定义的行为。在大多数情况下,链接器会告诉您函数已被多次定义,但您不能完全依赖它。

【讨论】:

    【解决方案2】:
    • 将代码拆分为文件提供了一个有用的逻辑分组来帮助理解您的程序。
    • 在许多情况下,拆分会加快编译速度。
    • 拆分将允许您执行具有循环依赖关系的事情(尽管应尽可能避免)。
    • 某些编译器将无法处理全部编译为一个main.cpp 的大型项目。

    【讨论】:

      【解决方案3】:

      如果您正在编写小玩具程序,那么将所有内容分解为逻辑上独立的模块可能会比花费更多的精力。我在我的硬盘上保存了几个 /hacks 项目,我在其中进行测试和实验,它们通常只是一个大文件。

      但是,当您开始研究实际系统时,事情会变得更加复杂。系统可以是数百万行代码或更多,在数千个不同的子系统中。将所有这些系统彼此分开可以为大型复杂系统带来许多好处。

      • 代码是为人类而非机器编写的。将系统分解成许多小文件就像写一篇有许多段落的文章,每个段落由几个(但不是太多)句子组成。用一个句子写一篇完整的 1000 字的文章也许是可能的,但读起来会很痛苦。同样,在数千个组织有序的小文件中找到您要查找的内容比在一个大文件中要容易得多。

      • 将文件(尤其是头文件)分解得尽可能小,但不能更小,这有助于大大加快编译速度。

      • 分解模块有助于分离不同的系统,并确定存在人工耦合的位置。

      总而言之,最重要的是它让事情变得更简单,这总是一件好事。

      【讨论】:

        【解决方案4】:

        在程序的不同“单元”之间进行清晰、合乎逻辑的划分有助于保持程序整洁。这有助于了解什么去哪里,什么使用什么,以及通常“它们如何组合在一起”。如果您只是将所有内容都包含在一个大代码块中,则很容易“无法正确分离事物”,因此突然之间在 B.cpp 中使用了 A.cpp 中的变量,而不是将变量声明为A.h 中的“extern”,或者更好的是,有一个函数可以从任何地方访问它,但实际变量在 B.cpp 中是“受保护的”,所以没有其他人可以使用它。

        “将事物分开”的技术称为封装——您只能看到文件头实际暴露的文件“位”。这样,作为您项目的第二个程序员,我知道我可以在 A.cpp 中更改哪些位(只要它工作相同) - 不在 A.h 中的所有内容都将是“公平的游戏”。必须更仔细地处理 A.h 中的内容,因为这意味着 A.cpp 之外的某些内容可能正在使用它,我们需要先查看在何处/如何使用它,然后才能对其进行更改。

        这对大型项目有很大影响。当你有 100 或 200 行代码时,你可以从字面上记住所有的代码行,如果你在 150-160 行改变了一些东西,你可以很容易地记住在 172 和 189 行也使用了相同的变量,所以你那里也需要改变。当你的项目有 2000 行长时,一个人一次了解大部分内容仍然是可以管理的。如果您已经编写了所有 100k 行,您可能仍然可以管理它。当您有 100 万行代码时,其中大部分是 ELSE 编写的,您需要良好的结构来改变事物,而不会导致无法正常工作的混乱。当然,如果你不表现出你一开始就明白应该如何完成,那么你将永远无法参与 5K 线项目。

        抱歉,这有点长,但总体思路是:如果您保持干净、整洁,您就有更好的工作方式,最终会产生更好的软件。

        【讨论】:

        • 好的......但我的问题有点不同。我问为什么要包含一个.h,在其中声明函数原型,如果我可以在没有声明的情况下直接将它们写在cpp中,那么将它们写在cpp中?
        • 我认为这就是我试图解释的:如果您将 .cpp 文件分开 [通过一次编译一个],我们知道 A.cpp 使用 B.cpp 中的某些内容,因为编译器会告诉我们何时发生。如果您将所有内容都写在一个大文件中,那么首先很难分辨出什么是什么在 A.h 或 B.h 中“告诉”它们属于一起。
        • 我不是说为什么要分开代码。我问为什么我需要在 .h 中声明函数原型并在 .cpp 中编写函数,如果我可以将它们写在 .cpp 中并将其包含在 main 中。例如,我想在单独的文件中编写一个类(不在 main.cpp 中)。我可以使用 #ifndef #define .. 在 .h 中声明该类,并将该类本身编写在 cpp 中,最后将 myclass.h 包含在 main.cpp 中。但我也可以制作一个 myclass.cpp 并在其中编写类而无需 .h 声明,并将其包含在 main.cpp 中。所以我的问题是:这两种方法有什么区别
        • 是的,你可以把它全部写在 main.cpp 中——因为这基本上就是包含 .cpp 文件的内容。当您有 378000 行代码时,您可能希望它比这更简单一点。当然,在调试时,找出要查看的源文件很简单。但是找出哪条线不会那么有趣。通过拆分事物,我们可以将组件彼此隔离,并且通过一次编译一个 .cpp 文件,我们知道我们的隔离是有效的。如果您只是将所有 .cpp 文件包含到 main.cpp 中,即使不是故意的,您也可以使用您不应该使用的东西。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        • 2012-08-13
        • 1970-01-01
        • 2018-07-02
        相关资源
        最近更新 更多