【问题标题】:#import in header file or implementation file#import 在头文件或实现文件中
【发布时间】:2010-11-19 03:38:44
【问题描述】:

有些人有在头文件中添加头文件导入/包含的习惯。另一方面,在头文件中编写前向声明并在实现文件中编写实际的#include 或#import 行。

这有标准做法吗?哪个更好,为什么?

【问题讨论】:

    标签: c++ objective-c c coding-style


    【解决方案1】:

    鉴于 X.h 和 X.c,如果您 #include 来自 X.h 的所有内容,那么 #include <X.h> 的“X”客户端也将包含所有这些标头,即使某些可能仅在 X.c 中需要。

    X.h 应该只包含解析 X.h 所需的内容。它应该假设翻译单元不会包含其他标题,以确保重新排序包含不会破坏客户端。 X.c 应包括实施所需的任何额外内容。

    这最大限度地减少了重新编译的依赖性。您不希望仅对实现进行更改以影响标头并因此触发客户端重新编译。您应该直接从 X.c 中包含。

    【讨论】:

      【解决方案2】:

      当类具有浅依赖时,需要包含前向引用而不是标头。例如:

      啊.h

      #include "B.h"
      class A {
         B* pointer;
      };
      

      B.h

      #include "A.h"
      class B {
         A* pointer;
      };
      

      会在编译时中断。

      啊.h

      class B;
      class A {
         B* pointer;
      };
      

      B.h

      class A;
      class B {
         A* pointer;
      };
      

      将起作用,因为每个类只需要知道声明中存在另一个类。

      【讨论】:

      • 在现实世界中具有这样的循环依赖是一种好的设计/架构吗?
      • 不,不是,应该尽可能避免。如果这是不可避免的,并且两个模块需要相互包含,那么在 99% 的情况下,它们在语义上是同一个模块,或者可以是两个都依赖的组合的基本模块的超级模块。
      • 最好为 A 和 B 提供前向声明头,它们分别只包含“A 类”和“B 类”,并且都包含在 A.h 和 B.h 中。这样,在从 A 构建任何东西(包括它的测试用例)时,A 的前向声明、声明和实现自然是交叉引用的,因此从类 A 更改为说一些模板和 typedef 不会让 B 对编译器撒谎A 是。
      • @Santiago:是的,软件模块中的循环依赖通常是不好的做法。但在个别类中,循环引用在许多情况下既常见又必要。在我的脑海中,父指针通常会创建循环引用。
      • 真的,我根本不提倡使用它们,只是解释必须使用前向声明的情况。我不明白你为什么会投反对票。
      【解决方案3】:

      我将导入写入头文件,因此每个实现文件只有一个包含指令。这还具有对模块代码的用户隐藏依赖项的优点。

      但是,同样的隐藏也有一个缺点:您的模块的用户可能会导入包含在您的标头中的各种其他标头,而他可能根本不需要这些标头。从这个角度来看,最好在实现文件中包含包含指令,即使这意味着手动解决依赖关系,因为它会导致代码更轻。

      我认为没有单一的答案。考虑到我给出的原因,我更喜欢第一种方法,我认为它会导致代码更简洁(尽管更重并且可能有不必要的导入)。

      我不记得我在引用谁(因此这个短语并不准确),但我总是记得读到:“程序是为人类阅读而编写的,偶尔是为了让计算机执行”。我并不特别关心我的模块的用户是否不需要几千字节的代码,只要他可以干净、轻松地导入它并通过单个指令使用它。

      再一次,我认为这是一个品味问题,除非有什么我没有考虑到的。在这种情况下,我们非常欢迎发表评论!

      干杯。

      【讨论】:

      • 抱歉 - 但您的逻辑混乱,您的偏好与公认的最佳实践相反。第 1 段:“这还具有向模块代码的用户隐藏依赖项的优点。” /“只要他可以干净,轻松地导入它并与单个指令一起使用”。您应该包含解析标头所必需的内容,任何其他仅用于实现的标头都不必包含在内,客户端仍然可以使用该功能。 (无论哪种方式,客户端仍然需要在对象/库上添加链接器依赖项。)
      • 老实说,我不明白我的逻辑是如何混乱的。将文件添加到编译行与强制某人在他的代码中导入多个模块是不一样的。然而,我所看到的是你是如何高度不尊重人的,所以请不要再发表任何评论。我会自己看看这方面的文章,然后下定决心。
      猜你喜欢
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      相关资源
      最近更新 更多