为什么在C ++中将类声明和定义放在两个单独的文件中?

时间:2009-05-17 02:09:56

标签: c++

我只是想知道,将类分成.h和.cpp文件的重点是什么?它使编辑变得更加困难,如果您的类不会被编译成.lib或.dll以供外部使用,那么重点是什么?

编辑: 我问的原因是Boost库将所有内容放在.hpp文件中(大多数库都是这样),我想知道为什么它在我看到的大多数其他代码中都是分开的。

7 个答案:

答案 0 :(得分:17)

C ++有一种称为单一定义规则的东西。这意味着(不包括内联函数),定义只能出现在一个编译单元中。由于C ++头文件只是在每个包含文件中“复制并粘贴”,所以如果只是将定义放在头文件中,现在就将定义放在多个位置。

当然,你可能会说,为什么不把一切都内联。好吧,如果编译器尊重你的内联建议,那么长函数的代码将在每个调用站点被复制,使你的代码过大,并可能导致颠簸,缓存问题和各种未完成的东西。

另一方面,如果编译器不听你的话,并且没有内联任何内容,那么现在你有两个问题:1)你不知道哪个翻译单元得到你的类定义,2)编译器每当你#include他们时,仍然需要涉及你的定义。此外,没有简单的方法可以确保您没有意外地在两个不同的标题中两次定义相同的方法,不同。

您还会遇到循环依赖问题。对于要调用另一个类的方法的类,需要首先声明该类。因此,如果2个类需要调用彼此的方法,则必须先声明每个类,然后才能定义它们。在一个文件中无法使用声明和定义执行此操作。

真的,这就是语言和解析器的构建方式。这是一种痛苦,但你只需处理它。

答案 1 :(得分:4)

嗯,以这种方式使用代码的好处之一是它减少了编译时间。

假设您的项目中包含以下文件:

  • A.H
  • a.cpp
  • b.cpp

如果您已将a.cpp编译到目标文件 ao 中,那么如果在 b.cpp 中包含 ah ,则编译应该更快,因为解析器不必处理 a 的整个声明/定义。

答案 2 :(得分:4)

Boost没有内联所有代码;它为其期望消费者实例化的类内联模板定义,如shared_ptr。许多库都有需要单独编译的部分,如boost :: serialization和program_options。

随着代码库大小的增加,内联可能会产生严重的负面影响。它增加了组件之间的耦合,更不用说编译你的编译时间了(由于其他很多原因,这种情况有所提升:)。实际上,您的所有翻译单元几乎都有一个完整的程序副本,一个微小的变化将导致您重建/重新测试所有内容。在某些项目中,这可能需要很多小时。

我从来没有真正注意到编辑更难;根据我的经验,由于界面和实现的明确分离,它变得更容易,我知道要找哪个文件来找到我正在寻找的东西。

答案 3 :(得分:2)

因为即使在你的DLL中,其他类也会使用你的类。这些文件必须在编译时通过包含.h来查看类声明。他们不能看到定义,或者会有多个类函数的定义。

答案 4 :(得分:2)

您的编辑重播:Boost是一个重要的区别。由于编译器和链接器在当前C ++标准中的工作方式,模板类几乎总是在头文件中定义。您会发现大多数模板库(不仅仅是Boost)都是在头文件中实现的,原因相同。

答案 5 :(得分:0)

在C ++中,单独编译代码模块(.c或.cpp文件)需要在使用之前定义函数原型。如果要使用其他位置定义的类或方法,则必须导入.h文件以获取其定义。最后,链接器确保所有c / cpp文件都能满足.h文件中的所有promise。

此外,它允许仅通过定义.h文件来创建整个框架,例如boost。

答案 6 :(得分:-1)

因为在大多数情况下,除了实现它的文件之外,您还希望使用该类。如果您将整个程序放在一个文件中,则不需要分离。

你几乎不想在一个文件中编写C ++程序。