对于必须处理分布在多个源文件和头文件中的大量相互依赖类的人,您建议使用哪些C ++编码和文件组织指南?
我在我的项目中遇到这种情况,解决跨越几个头文件的类定义相关错误已经变得非常头疼。
答案 0 :(得分:66)
一些一般性指导原则:
foo.cxx
,则最好在foo.h
中声明所有内容。#include
发出声明。这允许您打破循环标头依赖项。本质上,对于跨单独文件的循环依赖,您需要一个类似于下面的文件依赖图:
A.cxx
需要A.h
和B.h
B.cxx
需要A.h
和B.h
A.h
需要B.h
B.h
是独立的(以及A.h
中定义的前向声明类)如果您的代码旨在成为其他开发人员使用的库,则还需要执行一些其他重要步骤:
include/
和src/
子目录,其中include/
包含我的所有公共标题,src/
包含我的所有来源。和私人标题。我建议找一本John Lakos的书大型C ++软件设计。这是一本非常沉重的书,但是如果你只是略过一些关于物理架构的讨论,你会学到很多东西。
答案 1 :(得分:8)
在NASA Goddard Space Flight Center查看C和C ++编码标准。我在C标准中特别注意并在我自己的代码中采用的一条规则是强制执行头文件的“独立”性质的规则。在头文件xxx.h的实现文件xxx.cpp中,确保xxx.h是包含的第一个头。如果标头在任何时候都不是自包含的,则编译将失败。这是一个非常简单而有效的规则。
它失败的唯一一次是你在机器之间移植,而xxx.h标头包括,例如<pqr.h>
,但是<pqr.h>
需要碰巧由标头提供的设施{原始平台上的{1}} {<abc.h>
包括<pqr.h>
},但<abc.h>
在其他平台上无法使用这些工具(它们位于<abc.h>
中,但def.h
不包含<pqr.h>
)。这不是规则的错误,如果您遵循规则,问题就更容易诊断和修复。
答案 2 :(得分:6)
答案 3 :(得分:5)
Tom's answer非常棒!
我唯一要补充的是永远不会在头文件中使用“声明”。它们只应该被允许在实现文件中,例如foo.cpp
。
这本书的逻辑在优秀的书籍“Accelerated C ++”(Amazon link - 为脚本小子链接纳粹消毒了)中有详细描述。
答案 4 :(得分:3)
除此之外还有一点:
不要包含任何私人定义 在包含文件中。例如。任何 仅用于的定义 xxx.cpp应该在xxx.cpp中,而不是 xxx.h.
看起来很明显,但我明白了 频繁。
答案 5 :(得分:3)
我想添加一个非常好的练习(在C和C ++中),这经常被抛弃:
#include "foo.h" // always the first directive
应该遵循任何其他所需的标题,然后是代码。关键是你几乎总是需要这个编译单元的头,并且包括它作为第一个指令保证头保持自给自足(如果不是,将会有错误)。对于公共标题尤其如此。
如果在任何时候你需要在这个标题包含之前添加一些东西(当然除了评论),那么很可能你做错了。除非你真的知道你在做什么......这导致另一个更重要的规则=&gt;评论你的黑客!