在C或C++中,如何记录函数文档?

46

我有一个包含多个文件的C程序,例如,stuff.c实现了一些函数,而stuff.h则包含了这些函数的原型。

我该如何在注释中记录这些函数的文档?

应该将所有文档都放在头文件中,还是都放在.c文件中,或者将文档复制到两个文件中?我喜欢后一种方法,但是我会遇到问题,即我会更新其中一个文件的文档,而忘记更新另一个文件(通常是我首先修改的文件,例如如果我首先修改头文件,则它的注释将反映出这一点,但如果我更新实现,则只有那些注释会更改)。

对于C++代码,此问题及其答案也适用——请参见 在哪里放置文档注释?

10个回答

89
  • 将函数使用者需要知道的信息放在头文件中。

  • 将函数维护者需要知道的信息放在源代码中。


15

我喜欢遵循Google的C++样式指南

其中写道:

函数声明

  • 每个函数声明都应该紧接在其前面有一段注释,描述函数的作用和使用方法。这些注释应该是描述性的(“打开文件”),而不是命令式的(“打开文件”);注释描述函数的功能,而不是告诉函数如何执行任务。一般来说,这些注释不应该描述函数如何执行任务,这应该留给函数定义中的注释。

函数定义

  • 每个函数定义都应该有一个注释,描述函数的作用以及它如何完成任务的任何棘手的问题。例如,在定义注释中你可以描述你使用的任何代码技巧,概述你所经历的步骤,或者解释为什么你选择实现该函数的方式,而不是使用可行的替代方案。例如,你可能要提到为什么它必须在函数的前半部分获取锁,但为什么在后半部分不需要。

    请注意,你不应该只是重复在函数声明中给出的注释,无论是在.h文件还是其他地方。可以简要地概述函数的作用,但注释的重点应该是如何实现它。


11
你应该使用一个类似 doxygen 的工具,这样文档就可以由代码中特别编写的注释自动生成了。

9
我曾反复思考过这个问题,最终我选择在头文件中编写文档。对于大多数C/C++ API,您可以访问原始的头文件,因此可以查看其中所有的注释[1]。将注释放置在此处可以最大限度地增加开发人员查看它们的机会。
但我避免在头文件和源文件之间重复注释(这只是浪费时间)。在使用Vim时这很烦人,但大多数IDE都会获取头文件中的注释并将其放入类似于Intellisense或参数帮助之类的东西中。
[1] 这条规则的例外包括某些COM库生成的头文件。

7
通常取决于编码标准的设置。许多人喜欢将文档放在.h文件中,将实现留在.c文件中。许多具有代码完成功能的IDE也更容易捕捉到.h文件中的文档,而不是.c文件中的文档。
但我认为将文档放在.h文件中的主要原因是编写将与另一个程序共享的库或程序集。想象一下,你正在编写一个包含组件的.dll(或.so)文件,你将要分发它。其他程序员将包括您的.h文件,但他们通常不会拥有(也不需要)其背后的实现文件。在这种情况下,在.h文件中的文档是无价之宝。
当您编写用于同一程序中的类时,也可以这样说。如果您与其他程序员一起工作,则大多数情况下,这些程序员只查看头文件以了解如何与您的代码交互,而不是如何实现代码。如何实现并不是使用该组件的人或代码的关注点。因此,再次,在头文件中编写文档将帮助那个人或那些人弄清楚如何使用该代码。

4

请考虑人们可能只有头文件和已编译的实现版本就能使用这些函数。确保在头文件中记录使用您的函数所需的任何内容。实现细节可以在源代码中记录。


3

一定要将文档放在一个地方,以避免维护上的噩梦。你个人可能足够认真,可以保持两份副本同步,但下一个人不会。

使用类似doxygen的工具创建“漂亮”的文档版本。


3

头文件中的注释与实现文件应反映两者使用方式的不同。

如果您要创建接口文档(例如,要使用Doxygen提取的文档,与JavaDocs的一般顺序相同),则明显属于头文件。即使您不打算提取注释以生成单独的文档,也适用相同的一般思想 - 解释接口/如何使用代码的注释主要或仅属于头文件。

实现中的注释通常与实现相关。与频繁实践相反,大多数注释应该解释为什么做出特定的决策而不是尝试解释如何工作。当您做出有意义但可能不明显的决策时,这一点尤其正确(例如,指出您没有使用Quicksort,因为您需要一个稳定的排序)。


3

当你思考这个问题时,它其实很简单。

API文档必须放在头文件中。因为头文件定义了外部接口,所以API文档需要放在那里。

通常情况下,实现细节应该对API用户隐藏。包括实现文档(除非它可能影响使用,例如时间复杂度等)。因此,实现文档应该放在实现文件中。

永远不要在多个地方重复文档。这将难以维护,并且一旦有人不得不更改它,它就会失去同步。


3
我写了一个简单的脚本,它以没有函数声明的模板头文件和有注释函数的源代码文件作为输入。该脚本从源代码文件中提取函数定义前的注释,并将其与相关的函数声明写入输出头文件中。这确保了:1)只有一个地方需要编写函数注释;2)标头文件和源代码文件中的文档始终保持同步。对函数实现的评论放在函数体中,不被提取出来。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接