代码之家  ›  专栏  ›  技术社区  ›  JustJeff

解开.h依赖项

  •  4
  • JustJeff  · 技术社区  · 17 年前

    当你有一组.h文件成为经典的“Gordian结”的牺牲品时,你会怎么做?在哪里包括一个.h文件意味着你最终包括了几乎所有的文件?预防显然是最好的药物,但如果在供应商之前发生了这种情况,您会怎么做?图书馆已经发货了吗?

    这是问题的扩展,这可能是更切题的问题。-- 应该 你甚至试图从一开始就解开依赖关系?;

    4 回复  |  直到 17 年前
        1
  •  4
  •   quamrana Ryuzaki L    11 年前

    我已经在C++代码库上完成了这一任务,它已经被分割成多个库(这是一个很好的开始)。

    我必须锻炼(或猜测)哪个库最依赖,哪个库不依赖于代码库中的其他任何东西。然后我依次处理每个库。

    我依次查看每个模块(*.cpp文件),并确保首先包含它自己的头文件,然后将其余的文件注释掉,然后将该头文件中的所有包含内容注释掉,然后重新编译该模块,让编译器告诉我需要什么。我将取消对第一个似乎需要的头的注释,并检查那个头,必要时递归。有趣的是,有多少头最终不需要了。

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

    当您注释掉includes时,编译器非常有助于告诉您依赖项是什么(您需要使用所有必须维护可移植性的编译器重新编译)。

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

        2
  •  1
  •   caskey    17 年前

    有了这个机会,您应该重构代码以减少过大的包含量,但前提是您可以实现某种包内聚力。如果只是为了发现代码的每个用户无论如何都必须包含所有元素而将事情搞清楚,最终结果是相同的。

    另一个选项是使用定义来配置打开和关闭部分。不管怎样,对于现有的代码库,解决方案是朝着包内聚的方向发展。

    阅读: http://ivanov.files.wordpress.com/2007/02/sedpackages.pdf 并对包装内聚力的相关问题进行了研究。

        3
  •  1
  •   Chris Arguin    17 年前

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

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

        4
  •  0
  •   Jonathan Leffler    17 年前

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

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

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

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