在c++中,什么时候需要分别在“.h”文件中声明一个类,并在“.cpp”文件中提供函数实现?

When is it necessary to separately declare a class in a ”.h” file and provide the function implementations in a ”.cpp” file in c++?

本文关键字:文件 并在 一个 实现 函数 cpp 声明 什么时候 c++      更新时间:2023-10-16

何时需要在"。h "文件中单独声明一个类并提供功能实现在"。cpp"文件?

就c++语言而言,这不是严格必要的。您可以将所有类方法内联放在.h文件中。

但是,将实现放在单独的.cpp中可以提供许多好处,例如:

  1. c++非常复杂。随着代码的增长,编译它所需的时间会越来越长。每个包含相同头文件的.cpp文件将最终编译相同的代码,一遍又一遍。

  2. 与第一点相关:如果对类的方法做了任何更改,如果所有的类方法都在一个单独的.cpp文件中,只有.cpp需要重新编译。如果所有的类方法都内联地放在.h文件中,那么包含will的.cpp必须重新编译。

  3. 通常,类的方法将使用其他类作为完成它们需要做的事情的一部分。因此,如果它们都内联放置在.h文件中,则定义其他类的.h文件也需要包含在内,这也减慢了包含头文件的每个.cpp文件的编译速度。如果类方法在单独的.cpp文件中,则只有.cpp文件需要包含其他头文件,并且大多数情况下只需要向.h添加一些前向声明。

这样做是为了只构建一次类的代码。如果将类代码放在.h文件中,那么获取.h(以访问类的公共函数)的每个文件也将复制类代码。编译器会很乐意为您做这些。然而,链接器会强烈抱怨命名空间中重复的左值。

沿着同样的路线,但相反:内联函数需要在.h中,以便它们的代码将在其他代码文件中拾取,这正是内联函数的目的。

如果你想使用声明来实现/定义函数,你不想在*.h文件中看到的声明,那么就有必要将函数的定义移动到一个单独的文件中。

通常这是类定义(.h)和类实现(.cpp)之间的一个很好的分离,人们可以只阅读.h文件来了解和使用类,而无需费心阅读实现细节。

这是,然而,不是强制性的总是分开.h.cpp,你可以有类的定义和实现在一个单一的文件(例如。

从技术角度来看(就编译器需要或将接受的内容而言),这几乎是没有必要的——可以将每个(非标准)头文件的内容复制/粘贴到包含它们的源文件中,然后编译它们。毕竟,这实际上就是预处理器对#include指令所做的事情——将包含的文件复制到适当的位置,然后将生成的源代码提供给编译器的后续阶段。

在编译源代码时,编译器可能会耗尽内存——在这种情况下,将程序分成更小的部分,包括头文件,可以有所帮助——但是这种情况(在硬件资源非常有限的机器上,比如内存)在现代开发中是非常罕见的。

然而,在处理源文件时,人类比编译器更不一致,更容易出错,所以人类从使用头文件中受益。例如,不要将需要的声明输入(或复制)到需要它们的每个源文件中(这是一种人们觉得无聊的活动,而且容易犯错误),只需将声明放在头文件中,并在需要时将其#include

那么问题就来了,什么时候在头文件中放置声明会让人们的生活更轻松,允许他们避免犯错误,并将他们的精力集中在软件开发的创造性部分(实现新东西)而不是机械的(将函数声明复制到需要它们的源文件中)。

在实践中,通常情况下,将在多个编译单元(即源文件)中使用的类最好定义在头文件中。对于单个编译单元来说是局部的类(例如,包含不需要其他编译单元直接访问的编译单元的实现细节)不需要在头文件中,因为它可以直接定义而不需要使用头文件。如果这些"局部"类以后需要在其他编译单元中使用,那么问题就来了——在这种情况下,通常建议将必要的声明迁移到头文件中,以帮助重用。

头文件对于库的作者来说也是必要的——他们编写了一组函数供其他程序员使用,但不希望发布源代码。这是一个非技术约束(即基于策略),而不是技术约束。在这种情况下,他们可以分发头文件和编译的对象(或库)文件,并保持源代码的私密性。当然,从技术上讲,它们可以提供一组文本文件,其形式为"在需要时将这些声明复制到程序中",而不是头文件.....但是这将使库不受开发人员的欢迎,因为它迫使他们回到平凡且容易出错的复制文本活动中,而不是进行有用的开发。

诸如减少编译时间之类的考虑也是非技术原因(编译器并不关心构建程序需要多长时间,但人们关心)。将类定义分离为头(类定义,任何内联函数)和单独的源(非内联成员函数的定义)确实有助于减少构建时间,并有助于增量构建。