数千行代码不知所措?
在目录中每个类具有一组头文件/源文件似乎有点过头了。如果班级数量达到100或1000,甚至会令人恐惧。
但是,按照“让所有东西放在一起”的理念玩弄了源代码之后,得出的结论是,只有撰写文件的人才有希望不会丢失。即使使用IDE,也很容易遗漏任何东西,因为当您处理20,000行的源代码时,您会为任何与您的问题不完全相关的事情而闭嘴。
现实生活中的例子:在这千行源代码中定义的类层次结构将自身封闭为菱形继承,并且某些方法在子类中被具有完全相同代码的方法覆盖。这很容易被忽略(谁想浏览/检查20,000行源代码?),并且当更改原始方法(错误纠正)时,效果不如预期的普遍。
依赖关系变得循环了吗?
我在模板代码中遇到了这个问题,但是在常规C ++和C代码中也遇到了类似的问题。
将源分成每个结构/类1个标头,您可以:
- 加快编译速度,因为您可以使用符号前向声明而不是包括整个对象
- 类(§)之间具有循环依赖关系(即,类A具有指向B的指针,而类B具有指向A的指针)
在源代码控制的代码中,类依赖关系可能导致类在文件中上下移动,以使标头得以编译。在比较不同版本的同一文件时,您不想研究此类移动的演变。
具有单独的标头可以使代码更具模块化,编译速度更快,并且可以更轻松地通过不同版本的差异来研究其演变
对于我的模板程序,我必须将标头分成两个文件:包含模板类声明/定义的.HPP文件,以及包含上述类方法的定义的.INL文件。
将所有这些代码放在一个且只有一个唯一的标头中,意味着将类定义放在此文件的开头,并将方法定义放在末尾。
然后,如果某人只需要一小部分代码,并且仅使用一个标头的解决方案,他们仍然将不得不为较慢的编译付出代价。
(§)请注意,如果知道哪个类拥有哪个类,则可以在类之间具有循环依赖关系。这是关于知道其他类的存在的类的讨论,而不是shared_ptr循环依赖关系反模式。
最后一句话:标题应该是自给自足的
但是,必须通过多个标头和多个源的解决方案来尊重这一点。
当您包含一个标头时,无论使用哪个标头,您的源代码都必须干净地编译。
每个标题都应该是自给自足的。您应该开发代码,而不是通过捉住10,000多个源文件项目来寻宝,以发现哪一个标头定义了仅因一个枚举而需要包含的1,000行标头中的符号。
这意味着每个标头都定义或正向声明其使用的所有符号,或者包括所有必需的标头(并且仅包含必需的标头)。
关于循环依赖的问题
下划线-d问:
您能解释一下使用单独的标题对循环依赖有何影响吗?我不这样认为。即使两个类都在同一个标头中完全声明,我们也可以简单地创建一个循环依赖关系,只需在我们在另一个声明句柄之前预先向前声明一个就可以了。其他所有内容似乎都是不错的地方,但是分开的标题有助于循环依赖的想法似乎遥不可及
underscore_d,11月13日在23:20
假设您有2个类模板A和B。
假设类A(分别为B)的定义具有指向B(分别为A)的指针。我们还说A类(分别为B)的方法实际上是从B(分别为A)调用方法的。
您在类的定义及其方法的实现中都具有循环依赖关系。
如果A和B是普通类,并且A和B的方法在.CPP文件中,则不会有问题:您将使用前向声明,为每个类定义提供标头,然后每个CPP都将包含两个HPP。
但是,因为有了模板,实际上您必须在上面重现该模式,但仅使用标头。
这表示:
- 定义头A.def.hpp和B.def.hpp
- 实现标头A.inl.hpp和B.inl.hpp
- 为了方便起见,“天真”标头A.hpp和B.hpp
每个标头将具有以下特征:
- 在A.def.hpp(分别为B.def.hpp)中,您具有B类的前向声明(resp.A),这将使您能够声明对该类的指针/引用
- A.inl.hpp(分别为B.inl.hpp)将同时包括A.def.hpp和B.def.hpp,这将使A(分别为B)中的方法能够使用B类(分别为A) 。
- A.hpp(分别为B.hpp)将直接包含A.def.hpp和A.inl.hpp(分别为B.def.hpp和B.inl.hpp)
- 当然,所有标头都必须自给自足,并由标头防护装置保护
天真的用户将包括A.hpp和/或B.hpp,从而忽略了整个混乱。
具有这种组织结构意味着库编写者可以解决A和B之间的循环依赖关系,同时将两个类都保存在单独的文件中,一旦您了解了该方案,就可以轻松浏览。
请注意,这是一个极端情况(两个模板彼此了解)。我希望大多数代码都不需要该技巧。