将应用程序级别的代码分为“include”和“src”文件夹?

73

这个问题主要涉及Unix/Linux风格的C++开发。我发现许多C ++将其头文件存储在“include”文件夹中,源文件存储在“src”文件夹中。为了符合规范,我在自己的代码中也采用了这种方式。但我不确定是否应该对应用程序代码执行此操作。我看到过一些情况下使用扁平的目录结构。哪种方法是推荐的?

10个回答

71

我也将它们分开,但不是严格按照扩展名,而是按文件访问来分类。

假设你有一个模块管理客户信息,并使用 2 个类来完成这个功能:Customer 与 CustomerValidityChecker。同时,假设应用程序中的其他部分只需要知道 Customer 类,而 CustomerValidityChecker 仅由 Customer 类用于执行一些检查。

基于这些假设,我将文件存储如下:

公共文件夹(或包含文件夹):

  • customer.h

私有文件夹(或源文件夹):

  • customer.cpp
  • customervaliditychecker.h
  • customervaliditychecker.cpp

这样,调用者就立即清楚哪些部分是可访问的(公共),哪些部分是不可访问的。


+1,我在工作中也使用相同的分离方式。当您每天与至少十几个组件进行交互时,让它们不会用您不关心的内容阻塞API文件是很方便的。 - Matthieu M.
我也想知道它是否会对构建时间产生一定的影响。例如,在Visual Studio的“附加包含目录”中,拥有一个包含较少文件的文件夹是否会比一个包含许多其他不应在库外被包含的头文件的文件夹更快? - jxramos
你是指公共的或私有的意思 - 是公共对于用户的web服务器,还是公共对于代码的其余部分?类可能有私有方法和数据,以及私有类和数据。另外,在lib和src之间,哪一个被认为是私有的而哪一个是公共的?我对这个答案感到困惑。 - ahnbizcad
@ahnbizcad,我的意思是对于代码的其余部分来说,必须不知道类实现的内部细节(你将头文件公开)。例如:如果您的应用程序使用GUI库,则必须公开对话框制作类的头文件,但.cpp文件必须是私有的。同样,仅由GUI内部使用的类(例如与图形设备的交互,像素绘图器等)可能应保持私有。同样,通常存在这样的情况,您希望使接口公开,但接口的实现是私有的。 - Patrick

13
我们有一个构建系统,可以自动生成我们的Makefile。其中一个功能是递归下降到任何子目录并将它们作为库进行构建,使用主目录对象将它们链接在一起以制作应用程序。(实际上,这些“子目录”通常是符号链接)。除非目录名称以“.so”结尾,否则库是静态的。这种方式的好处之一是系统的完全构建(该系统具有许多可执行文件)不必重复编译公共库。
但是,由于这个原因,没有头文件和源代码之间的分离。而且也从来没成为问题。老实说,我认为这样做更好,因为头文件和源文件的位置是相似的,您可以获取一个目录并知道您需要使用它的所有内容。它还与Subversion的“外部”特性以及其他版本控制系统中的类似特性完美配合。
最后一个在包含/ src分离失败的地方是如果您使用任何代码生成器,例如flex,bison或gengetopts。如果您将事情分散开来,则很难确定这些工具应该放置其输出以便进行构建。

4
老实说,我喜欢把头文件和源文件放在一起。还希望它们在一个Visual Studio的过滤器下,这样头文件和源文件可以放在一起。 - StackedCrooked
同意。如果您有一个细粒度的模块化,那么您最不想要的就是比文件更多的目录。如果您分离includesrc,那么您甚至需要进一步的include/libname目录,因为否则您将需要疯狂的#include "blabla/include/header.h"指令。 - Patrick Fromberg

11

对于共享库而言,将它们分离是有意义的,因为它们可能以编译形式分发,没有源代码。我见过一些项目将“公共”头文件(可由项目或库外部的代码访问的头文件)分离出来,同时将“私有”头文件和源文件放在同一个目录中。我认为,在编写共享库或应用程序级别代码时,使用一致的方法是很好的,因为你永远不知道何时需要将应用程序级别编写的内容转换为更低级别的库,并被多个项目共享。


6
很多事情取决于项目的规模。在几十个文件左右的情况下,将它们放在一个目录中更方便。对于包含数百或数千个文件的大型应用程序,您开始寻找将它们分开的方法(尽管在我参与的项目中,这是根据功能线而不是src/include完成的)。在这两者之间,可能还存在争议。

是的,当文件数量变得很大时,我开始想要额外的组织。有趣的是,这可能并没有太多好处。也许只是满足了某种分类强迫症 :) - StackedCrooked
为什么不使用更多的“src”子目录来保持每个目录中的文件数量较少呢? =) - Elliott

3

我不这样做;这似乎没有太大的优势。由于头文件往往与源文件有不同的扩展名,如果你真的感觉需要,可以让你的编辑器将它们分开显示--Visual Studio默认情况下会这样做,但我禁用了它,因为我更喜欢在一起看到它们。


2
对于库的客户端来说,有一个明显的优势:他们只需要知道一个包含目录;这减少了他们的维护开销,并降低了头文件名称冲突的风险... 实现者也会受益;他们可以更改其src目录的布局而不必担心破坏库客户端。 - Dan O

2
底线:仍在变化的源代码和头文件放在 /src 中。已经稳定的代码应该放在 /lib 和 /include 中(实际上,你可以把所有的 .lib 和它们的 .h 文件都放在 /lib 中)。
保持自己的源代码和头文件在一起,前提是它们要么是这个项目特定的,要么还没有被分解成共享库。
一旦主项目中某些源代码作为一个(相对稳定的)库被分解出来,就将 .a 或 .lib 放入 /lib 中,将其公共接口头文件放入 /include 中。
所有第三方库及其公共接口头文件也放入 /lib 和 /include 中。
正如其他人所指出的那样,从工具/IDE 访问 .h/.c 通常更兼容。但从组织角度来看,将正在改变的本地代码与稳定的库代码分开可能是有用的。

2
在我看来,两者都没有明显的优势。最终我决定将程序文件和头文件放在一起,因为我的编辑器(Visual SlickEdit)在它们没有分开时提供了额外的参考功能。

有趣的是,一个人的工具可以影响项目的许多方面。我同意以一种与IDE兼容的方式组织代码通常是个好主意。 - StackedCrooked

2

我几乎总是创建include和src文件夹来分离我的源代码。我认为这样可以使文件夹更加整洁,也更容易在我的IDE中找到文件。但我认为这只是一种口味问题。

任何一种方法都是有效的。这取决于您想要遵循的编码风格如何实现。


我的动机类似,都是因为我不喜欢杂乱无章的东西。 - StackedCrooked

1

我将头文件和源文件放在同一个目录(文件夹)中。我为不同的主题创建不同的文件夹。在调试和研究时,寻找头文件让我感到沮丧。有些商店只有两个文件夹:源代码和包含文件。这些目录往往会呈指数增长。重用代码最多成为一场噩梦。

在我看来,按主题组织更好。每个主题文件夹应该构建至少一个库。不同的项目可以通过搜索或包含文件夹轻松地包含主题。项目只需要包含库。智能构建引擎可以将主题文件夹列为依赖项。这加快了构建过程。

主题组织还为项目增加了一点安全性。由于文件位于不同的目录中,因此减少了对文件的意外损坏(例如删除错误文件或替换不同版本的文件)。删除“人物”文件夹中的文件不会影响“形状”文件夹中的文件。

这只是我的观点,你的情况可能会有所不同。


这与我目前工作的代码库相似。主要应用程序由许多实用工具组成,每个工具都有自己的svn仓库。主仓库通过svn externals收集所有内容。 - StackedCrooked

0

我们有一个构建系统,使用这个规则。这个构建系统是sconspiracy一组用于配置SCons并专门针对C++世界的脚本。您可以看到一个使用这些工具的示例:fw4spl


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