我正在使用C ++开展一个大项目。
我有很多类,它们的方法完全不同(例如一个转储,另一个修改对象,另一个检查它是否有效等等)。
为源文件(或可归档的一组目标文件)中的所有类实现方法的实现以及另一个归档中的另一个类的方法的所有实现是一种好的方式?
链接时这可能是好的,也许当某人不需要转储方法时(例如),或者最好将同一个类的方法实现保存在同一个源文件中,为了不混淆?
答案 0 :(得分:4)
需要权衡利弊。
当您更改任何函数的实现时,必须将整个翻译单元重新编译为新的目标文件。
如果每个翻译单元只编写一个函数,则可以最大限度地缩短因不必要的重建而导致的编译时间。
另一方面,每个翻译单元编写一个函数,你可以从头开始最大化编译时间,因为编译许多小TU的速度要慢于几个TU。
最佳解决方案是个人偏好,但通常介于“每个TU的单个功能”和“整个程序的一个大型TU”之间(而不是其中一个)。对于成员函数,每个类一个TU是一种流行的启发式方法,但不一定总是最佳选择。
另一个考虑因素是优化。对非内联函数的调用可以内联扩展,但只能在同一个翻译单元中扩展。因此,编译器更容易优化单个大型TU。
当然,您可以选择在头文件中定义内联函数,但这会导致重构问题,因为如果任何内联函数发生更改,那么包含头的所有人都必须重新构建。这比仅仅拥有更大的TU更糟糕,但没有像拥有一个大型TU那么糟糕。
因此,在同一个TU中定义相关的非内联函数允许编译器决定该TU内的优化,同时防止重新构建级联。如果这些相关功能将受益于内联扩展并相互调用,那么这将是有利的。
整个程序优化可以缓解这一优势。
第三个考虑因素是组织。查看类的成员函数的程序员可能也会对该类的其他成员函数感兴趣。将它们放在同一个源文件中可以让他们花更少的时间来搜索正确的文件。
将所有类函数分组到一个公共源文件中的组织优势在某种程度上可以通过现代IDE进行缓解,这些IDE允许从源文件快速跳转到标题并从那里跳转到另一个函数。
第四个考虑因素是编辑的表现。解析数万行或更多行的文件可能很慢并且可能使用大量内存,具体取决于解析技术。一个巨大的TU并不一定会导致这种情况,因为您可以使用仅包含在一起的单独文件。
另一方面,对于某些文件浏览器(现在可能不多)以及版本控制系统,大量文件可能会出现问题。
最后,我认为:我认为每个类的一个源文件是一个不错的启发式方法。但是当它不合适时,不应该虔诚地遵循它。
答案 1 :(得分:1)
有些组织的规则要求每个单元定义一个定义。在这些组织中,头文件只能定义一个类,而转换单元只能定义一个函数。其他组织最多为每个头文件命令一个源文件(某些头文件没有实现)。
最好的办法是介于两者之间。我通常不关心编译器或链接器性能。我非常关心代码可读性和可维护性。实现一些长达数千行的类的源文件很难导航。最好将该文件分成多个文件。将其分成数百个文件,每个函数一个文件,使得目录结构难以导航。将其分解为密切相关的函数块可以保持目录结构和每个文件的内容可导航。
然而,这是一个很大的问题:为什么你的班级如此之大,以至于你不得不为此担心?一个实现跨越数千行或几十个文件的类是代码味道。