【问题标题】:Is it a good practice to always create a .cpp for each .h in a C++ project?始终为 C++ 项目中的每个 .h 创建一个 .cpp 是一种好习惯吗?
【发布时间】:2010-12-11 08:19:20
【问题描述】:

有些类,如异常或模板,只需要头文件(.h),通常没有与它们相关的.cpp。

我已经看到一些项目(对于某些类)没有任何与头文件关联的 .cpp 文件,可能是因为实现太短以至于直接在 .h 中完成,或者可能出于其他原因,例如模板类,其中必须在标头中包含实现。

你的意见是,如果一个类太短,我应该避免创建一个 .cpp 文件并直接在头文件上编写代码吗?如果代码写在头文件中,我是否应该包含一个空的.cpp,以便项目中的文件保持一致?

【问题讨论】:

    标签: c++ compilation header-files


    【解决方案1】:

    我不会添加不必要的 .cpp 文件。您添加的每个 .cpp 文件都必须进行编译,这只会减慢构建过程。

    一般来说,使用你的类将只需要头文件 - 我认为“空” .cpp 文件对项目的一致性没有任何好处。

    【讨论】:

    • 我不太同意,在头文件中编写的代码必须与包含的一样多次编译,而如果它在源代码 (.c) 中则只需编译一次文件。不过我同意这很方便,编译时间对我来说不是主要问题。
    • @Ben,假设将在 h 文件中编译的任何代码都是内联大小的代码(或者至少是可以添加到预编译头文件的代码)。因此,h 文件的编译时间不会成为问题。
    • @kidnamedlox:没错。 @Ben:如果您包含的代码大小大于应内联的大小,我同意 .cpp 文件是个好主意。只有当代码很小的时候,我觉得为了一个.cpp文件而放一个空的.cpp文件不是很好的做法。
    • 我只想对你认为应该只在头文件中的内容添加评论。
    • 我确实看到了一个优势,请参阅my answer。不过,尚不清楚这一优势是否重要到足以使其成为创建其他无用源文件的指南。
    【解决方案2】:

    不。如果 .cpp 中不需要任何内容​​,则不需要。

    【讨论】:

    • 除非您在设计中的某个地方存在循环依赖,而不是偶然。
    • 不确定您的意思...请解释一下。
    • 如果您希望以这种方式解决循环依赖关系,那么您确实有一些需要在 .cpp 中的内容,因此 Grumdrig 的答案仍然成立。
    【解决方案3】:

    始终为每个 .h 创建一个 .cpp 有一个优点,即使前者为空:它在编译时强制头文件是自包含的。这与 foo.cpp 中首先包含 foo.h 的guideline 有关:

    使用首选顺序,如果 dir2/foo2.h 省略了任何必要的包含,则 dir/foo.cpp 的构建将中断。因此,此规则确保构建中断首先显示给处理这些文件的人,而不是其他包中的无辜人员。

    【讨论】:

      【解决方案4】:

      它真的很适合课程:

      • 仅标题类:例如模板 课程
      • 标头和 cpp:分隔声明 从实施开始。
      • cpp only:你的 main() 可以在一个 其中。

      仅头文件源代码有时是编写可重用模板的唯一方法。请参阅 boost 了解大量此类示例。

      标头和 cpp 更“正常”。它将声明与实现分开,并且当编译器不必多次读取实现负载时可以加快编译速度。您可能想从这里开始,然后查看实施情况,如果 cpp 文件为空,您可以将其删除。
      这里的另一点是,您将在foo.cpp 的顶部添加您的#include "foo.h",以证明其他任何人都可以这样做并且不会出现编译器错误。

      仅限 Cpp 文件。 main() 可以住在这里,我已经将 cppUnit 测试类放在这样的文件中。

      【讨论】:

        【解决方案5】:

        经验法则,将相关类放在同一个文件中。主要不同的类需要放入自己的 .hpp 和 .cpp 文件中。这样做的原因是在大型项目中,您有多达 10,000 个类,并且将这么多文件放在用户和 IDE 面前通常会使事情中断。

        【讨论】:

          【解决方案6】:

          有很多非常有用和成功的库,就像 boost 中的许多库一样,它们是仅标头的。

          【讨论】:

            【解决方案7】:

            如果某些类很短并且似乎是可内联的,我倾向于将它们全部放在types.h 中——我认为唯一不值得使用 .cpp 文件的标头。

            但是,大多数课程都超出了仅进入标题的机会和进入types.h 的机会。

            我所做的一些例子。我认为实现三维矢量Vector3 的类值得其.h 和.cpp,尽管很简单。但是Position 真的不值得这样做;毕竟,它甚至会是一个 P.O.D.结构,如果不是因为我喜欢在那里实现的那个讨厌的getDistance()

            所以不——不是所有的类都应该拥有它们的 .cpp 和 .h 文件。但大多数人都这样做,而那些不确定的人绝对不会站在一个单独的头上。如果它们太短而无法单独放入标题中,那么它们要么与其他短类抱在一起,要么进入与它们密切相关的类的标题中。

            【讨论】:

              【解决方案8】:

              我的经验法则是,我需要多于一行代码来表达的任何方法都会放入.cpp 文件中。

              要进一步讨论这个问题,你可能想看看我的这个老问题:C++ code in header files。我不认为你的问题是完全重复的,但它足够接近你应该阅读它。

              【讨论】:

                【解决方案9】:

                另请参阅this question - 头文件只能用于声明。

                如果您在多个位置包含可编译代码(来自您的评论:“我是否应该避免创建 .cpp 文件并直接在头文件中编写代码?”),每次都会编译它(尽管您可能有预编译的头文件),链接器将解析(或不解析)臃肿的目标代码。

                仅仅因为类定义很小并不意味着它应该在头文件中,除非定义也与声明相同 - 例如另一个答案中提到的纯虚拟类或简单类型。

                【讨论】:

                • 不幸的是,并非所有编译器都支持链接时内联,甚至那些在编译时内联支持比链接时更好的编译器也是如此。因此,您需要将想要内联的小型关键函数放入标头中,或者像 Unity Builds 那样进行编译时扭曲。
                • 如果您打算在多个翻译单元中使用该类,则类定义必须位于标题中。也许您正在考虑类 methods 的定义?这些可以安全地保存在 .cpp 中。原因是链接器可以在链接时解析函数和方法,但不能解析整个类。
                • @MSalters:你的意思是类声明必须在标题中。
                猜你喜欢
                • 2011-06-22
                • 1970-01-01
                • 2015-02-04
                • 2012-11-09
                • 2019-07-15
                • 2011-01-28
                • 1970-01-01
                • 2017-08-09
                • 2020-12-14
                相关资源
                最近更新 更多