源文件中的代码排序 - 前向声明与“不要重复自己”?

时间:2009-01-19 00:19:33

标签: c++ c coding-style

如果您使用C编写代码并将编译器配置为坚持在使用它们之前声明所有函数(或者如果您使用C ++编写代码),那么您最终可以使用(至少)两个组织之一来处理源文件

或者:

  • 接头
  • 此文件中(静态)函数的前向声明
  • 外部功能(主要入口点)
  • 静态 - 非公开 - 功能

或者:

  • 接头
  • 静态 - 非公开 - 功能
  • 外部功能(主要入口点)

我认识到在C ++中,术语“静态”不是首选,但我主要是C程序员,并且C ++中存在等效概念,即文件中匿名命名空间中的函数。

问题:

  • 您使用哪个组织,为什么更喜欢它?

作为参考,我自己的代码使用第二种格式,以便在使用静态函数之前定义静态函数,这样就不需要声明它们并定义它们,从而节省了写入函数接口的信息。两次 - 当内部接口需要更改时,这反过来会减少(略微)开销。这样做的缺点是文件中定义的第一个函数是最低级别的例程 - 由文件后面定义的函数调用的例程 - 所以不是在顶部有最重要的代码,它更接近底部的文件。对你有多重要?

我假设所有外部可访问的函数都在头文件中声明,并且这种重复形式是必要的 - 我认为这不应该引起争议。

6 个答案:

答案 0 :(得分:6)

我一直使用方法#1,原因是我希望能够快速判断特定文件中定义了哪些功能,并在一个地方看到它们的签名。我没有找到必须更改原型以及函数定义特别有说服力的论点,因为你通常最终会改变调用已更改函数的所有代码,在你处理时更改函数原型似乎相对微不足道。 / p>

答案 1 :(得分:3)

在C代码中,我使用一个简单的规则:

  • 每个具有非静态成员的C文件都将有一个相应的头文件来定义这些成员。

这在过去对我来说非常有用 - 让我们很容易找到函数的定义,因为如果我需要查找它,它就在同名的.h文件中。它也适用于doxygen(我的首选工具),因为所有的cruft都保存在标题中,我不会花费大部分时间--C文件中充满了代码。

对于文件中的静态成员,我坚持按照这样的方式对声明进行排序,即无论如何都要在实例化之前定义它们。并且,我几乎一直在函数调用中避免循环依赖。

对于C ++代码,我尝试了以下内容:

  • 头文件中定义的所有代码。使用#pragma interface / #pragma implementation来告知编译器;有点像模板将所有代码放在标题中的方式。

在C ++中,这对我来说非常有用。这意味着你最终得到了HUGE头文件,在某些情况下会增加编译时间。你最终得到一个C ++正文文件,你只需要包含标题和编译。您可以在此处实例化静态成员变量。它也变成了一场噩梦,因为它很容易改变你的方法参数并破坏你的代码。

我搬到了

  • 带有doxygen注释的头文件(除了模板,代码必须包含在头文件中)和完整的正文文件,除了我知道我更喜欢在使用时内联的简短方法。

将实现与定义分开有一个明显的好处,就是更难以改变你的方法/函数签名,这样你就不太可能做到这一点并破坏事物。这也意味着我可以在头文件中有大量的doxygen块,记录代码中的工作和工作方式相对中断,除了有用的注释,如“声明一个名为i的变量”(舌头在脸颊)。

Ada强制执行约定和文件命名方案。大多数动态语言(如Ruby,Python等)通常不关心在何处/如果您声明事物。

答案 2 :(得分:2)

对我来说是第2号。

我认为使用静态或其他方法使模块函数和变量对模块是私有的是一种很好的做法。

我更喜欢将api功能放在模块的底部。相反,我把api函数放在我的类的顶部,因为类通常是可重用的。将api函数放在顶部可以更容易地快速找到它们。大多数IDE都可以直接带您进入任何功能。

答案 3 :(得分:2)

2:因为我写了许多简短的函数并自由地重构它们,所以维持前向声明会是一个很大的麻烦。如果有一个Emacs扩展可以为你做这件事而没有大惊小怪,我会感兴趣,因为自上而下的组织更具可读性。 (我更喜欢自上而下的例如Python。)

实际上并不完全是你的2号,因为我通常将.c中的相关功能组合在一起,无论它们是公共的还是私人的。如果我想查看所有公开声明,我会在标题中查看。

答案 4 :(得分:1)

(谈论C代码)

对我来说是2号因为我总是忘记更新前向decls以反映静态函数的变化。

但我认为最好的做法应该是

  • 标题
  • 前言声明+对每个人的功能行为的评论
  • 导出的函数+当代码不够清晰时,有关实现细节的最终评论
  • 静态函数+关于实现细节的最终评论

答案 5 :(得分:0)

  

对你来说多重要?

不是。

重要的是所有本地函数都将标记为static,但我认为定义如何在文件中对函数进行分组是太多了。任何版本都没有强有力的推理,我也没有找到任何强大的劣势。

一般来说,编码惯例是非常重要的,我们试图尽可能地定义,但在这种情况下我的感觉,这是不合理的开销。

再次阅读所有帖子之后,似乎我应该简单地upvote(我做过)Darius回答,而不是写下所有这些......