对于那些必须处理分布在多个源文件和头文件中的大量相互依赖的类的人,您建议使用哪些C++编码和文件组织指南?
我在我的项目中遇到这种情况,解决跨越几个头文件的类定义相关错误已经变得非常头疼.
一些一般准则:
将接口与实现配对.如果你有foo.cxx
,那里最好的东西最好被声明foo.h
.
确保每个头文件#include包含独立编译所需的所有其他必要头文件或前向声明.
抵制创造"一切"标题的诱惑.他们总是遇到麻烦.
将一组相关(和相互依赖)功能放入单个文件中.Java和其他环境鼓励每个文件一个类.使用C++,您经常需要每个文件有一组类.这取决于代码的结构.
#include
尽可能优先于s进行前瞻性声明.这允许您打破循环标头依赖项.本质上,对于跨单独文件的循环依赖,您需要一个类似于下面的文件依赖图:
A.cxx
要求A.h
和B.h
B.cxx
要求A.h
和B.h
A.h
要求 B.h
B.h
是独立的(和定义的前向声明类A.h
)
如果您的代码旨在成为其他开发人员使用的库,则还需要执行一些其他重要步骤:
如有必要,请使用"私有标题"的概念.也就是说,几个源文件需要的头文件,但公共接口从不需要.这可以是具有公共内联函数,宏或内部常量的文件.
在文件系统级别将公共接口与私有实现分开.我倾向于在我的C或C++项目中使用include/
和src/
子目录,其中include/
包含我的所有公共头文件,并且src/
拥有我的所有源代码.和私人标题.
我建议找一本John Lakos的书" 大规模C++软件设计".这是一本非常沉重的书,但如果你只是略过一些关于物理架构的讨论,你会学到很多东西.
查看NASA戈达德太空飞行中心的C和C++编码标准.我在C标准中特别注意并在我自己的代码中采用的一条规则是强制执行头文件的"独立"性质的规则.在头文件xxx.h的实现文件xxx.cpp中,确保xxx.h是包含的第一个头.如果标头在任何时候都不是自包含的,则编译将失败.这是一个非常简单而有效的规则.
它失败的唯一一次就是如果你在机器之间移植,并且xxx.h标头包括,比如说,
但是
需要设备恰好可以通过
原始平台上的标头提供(
包括
),但设施不是通过提供
其他平台(他们是在def.h
代替,但
不包括
).这不是规则的错误,如果遵循规则,问题就更容易诊断和修复.
检查Google样式指南中的标题文件部分
汤姆的答案很棒!
我唯一要补充的是永远不会在头文件中使用"声明".它们只应该被允许在实现文件中,例如foo.cpp
.
这本书的逻辑在优秀的书籍"Accelerated C++"(亚马逊链接 - 为脚本小子链接纳粹消毒)中有详细描述