【问题标题】:untangling .h dependencies解开 .h 依赖项
【发布时间】:2015-02-09 00:57:19
【问题描述】:

当您有一组 .h 文件成为经典“死结”情况的牺牲品时,您会怎么做,在哪里 #include 一个 .h 意味着您最终会包含几乎所有文件?预防显然是最好的良药,但是当这种情况发生在供应商(!)运送图书馆之前,你会怎么做?

这是问题的扩展,这可能是更相关的问题——是否应该您甚至首先尝试解开依赖关系?

【问题讨论】:

  • +1,我也有类似的问题..

标签: c dependencies projects


【解决方案1】:

我已经在一个已经分成许多库的 C++ 代码库上完成了这项工作(这是一个好的开始)。

我必须确定(或猜测)哪个库最依赖,它不依赖于代码库中的任何其他内容。然后我依次处理每个库。

我依次查看了每个模块(*.cpp 文件),并确保它自己的头文件首先被#included 并注释掉其余部分,然后我注释掉该头文件中的所有#includes,然后重新编译只是那个模块让编译器告诉我需要什么。我会取消注释似乎需要的第一个标题,并审查那个,必要时递归。有趣的是,最终不需要多少标头。

如果只需要名称(因为您有指针或引用),请使用class name;struct name;,这称为前向声明并避免#include 头文件。

当您注释掉 #includes 时,编译器会非常有帮助地告诉您依赖关系是什么(您需要使用所有必须保持可移植性的编译器重新编译)。

有时我不得不在库之间移动模块,这样就没有库对或库组相互依赖。

【讨论】:

  • +1 用于标头中的前向声明,完全包含在实现文件中。
【解决方案2】:

如果有机会,您应该重构代码以减少太大的包含,但这假设您可以实现某种包内聚。如果你解开事物只是为了发现代码的每个用户无论如何都必须包含所有元素,那么最终结果是一样的。

另一个选项是使用#defines 来配置部分的开启和关闭。无论如何,对于现有的代码库,解决方案是朝着包内聚的方向发展。

阅读:http://ivanov.files.wordpress.com/2007/02/sedpackages.pdf 并研究与包内聚相关的问题。

【讨论】:

    【解决方案3】:

    我已经解开这个结好几次了,在维护系统以尽可能减少 .h 依赖项时,它通常很有帮助。有一些不错的工具可以生成依赖树(我当时正在使用 Klocwork)。

    我发现的缺点是条件编译。有人可能会删除一个头文件,因为他们认为我们不需要它,但事实证明我们只是不需要它,因为 VxWorks 有一些搞砸的头文件......在 Solaris(或任何合理的 Posix 系统)上你确实需要它。

    【讨论】:

      【解决方案4】:

      在大量精心组织的标题和包含所有内容的单个标题之间需要取得平衡。考虑标准 C 库;有一些像<stdio.h> 这样的大标题,它声明了很多函数,但它们都与I/O 有关。还有其他一些标题更像是杂项 - 特别是 <stdlib.h>

      戈达德太空飞行中心的 C 指南值得一试。

      基本规则是每个标头都应声明由一组合适的(通常很小的)源文件提供的设施。设施和标题应该是独立的。也就是说,如果有人需要标头"something.h" 中的代码,那么它应该是唯一必须添加到编译中的标头。如果"something.h" 需要的设施未在标头中声明,则它必须包含相关标头。这可能意味着标题最终会包含<stddef.h>,因为其中一个函数使用了size_t

      正如@quamrana 指出的那样,您可以在适当的时候对结构(不是类,因为问题标记为 C 而不是 C++)使用前向声明 - 这主要意味着当接口采用指针并且不需要知道结构或任何成员。

      【讨论】:

        猜你喜欢
        • 2021-06-24
        • 2023-04-07
        • 2017-05-06
        • 1970-01-01
        • 2018-04-02
        • 1970-01-01
        • 2016-06-19
        • 2018-05-12
        • 2018-01-23
        相关资源
        最近更新 更多