C++类头文件组织
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/346058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ class header files organization
提问by Ashwin Nanjappa
What are the C++ coding and file organization guidelines you suggest for people who have to deal with lots of interdependent classes spread over several source and header files?
对于必须处理分布在多个源文件和头文件中的大量相互依赖的类的人,您建议的 C++ 编码和文件组织指南是什么?
I have this situation in my project and solving class definition related errors crossing over several header files has become quite a headache.
我在我的项目中遇到了这种情况,解决跨多个头文件的类定义相关错误已经变得非常头疼。
回答by Tom
Some general guidelines:
一些一般准则:
- Pair up your interfaces with implementations. If you have
foo.cxx
, everything defined in there had better be declared infoo.h
. - Ensure that every header file #includes all other necessary headers or forward-declarations necessary for independent compilation.
- Resist the temptation to create an "everything" header. They're always trouble down the road.
- Put a set of related (and interdependent) functionality into a single file. Java and other environments encourage one-class-per-file. With C++, you often want one set ofclasses per file. It depends on the structure of your code.
- Prefer forward declaration over
#include
s whenever possible. This allows you to break the cyclic header dependencies. Essentially, for cyclical dependencies across separate files, you want a file-dependency graph that looks something like this:A.cxx
requiresA.h
andB.h
B.cxx
requiresA.h
andB.h
A.h
requiresB.h
B.h
is independent (and forward-declares classes defined inA.h
)
- 将您的接口与实现配对。如果有
foo.cxx
,那么最好在foo.h
. - 确保每个头文件#includes 所有其他必要的头文件或独立编译所需的前向声明。
- 抵制创建“一切”标题的诱惑。他们总是在路上遇到麻烦。
- 将一组相关(和相互依赖)的功能放入一个文件中。Java 和其他环境鼓励每个文件一个类。使用 C++,您通常需要每个文件一组类。这取决于您的代码结构。
#include
尽可能优先使用前向声明而不是s。这允许您打破循环头依赖关系。本质上,对于跨单独文件的循环依赖,您需要一个看起来像这样的文件依赖图:A.cxx
需要A.h
和B.h
B.cxx
需要A.h
和B.h
A.h
需要B.h
B.h
是独立的(并且前向声明在 中定义的类A.h
)
If your code is intended to be a library consumed by other developers, there are some additional steps that are important to take:
如果您的代码旨在成为其他开发人员使用的库,则需要采取一些重要的额外步骤:
- If necessary, use the concept of "private headers". That is, header files that are required by several source files, but never required by the public interface. This could be a file with common inline functions, macros, or internal constants.
- Separate your public interface from your private implementation at the filesystem level. I tend to use
include/
andsrc/
subdirectories in my C or C++ projects, whereinclude/
has all of my public headers, andsrc/
has all of my sources. and private headers.
- 如有必要,请使用“私有标头”的概念。也就是说,几个源文件需要的头文件,但公共接口从来不需要。这可以是具有常见内联函数、宏或内部常量的文件。
- 在文件系统级别将公共接口与私有实现分开。我倾向于在我的 C 或 C++ 项目中使用
include/
和src/
子目录,那里include/
有我所有的公共头文件,也src/
有我的所有源代码。和私人标题。
I'd recommend finding a copy of John Lakos' book Large-Scale C++ Software Design. It's a pretty hefty book, but if you just skim through some of his discussions on physical architecture, you'll learn a lot.
我建议您找一本 John Lakos 的著作Large-Scale C++ Software Design。这是一本相当厚重的书,但如果你只是浏览他关于物理建筑的一些讨论,你会学到很多东西。
回答by Jonathan Leffler
Check out the C and C++ coding standards at the NASA Goddard Space Flight Center. The one rule that I specially noted in the C standard and have adopted in my own code is the one that enforces the 'standalone' nature of header files. In the implementation file xxx.cpp for the header xxx.h, ensure that xxx.h is the first header included. If the header is not self-contained at any time, then compilation will fail. It is a beautifully simple and effective rule.
在NASA Goddard 太空飞行中心查看 C 和 C++ 编码标准。我在 C 标准中特别指出并在我自己的代码中采用的一项规则是强制执行头文件的“独立”性质的规则。在头文件xxx.h 的实现文件xxx.cpp 中,确保xxx.h 是包含的第一个头文件。如果头在任何时候都不是自包含的,那么编译将失败。这是一个非常简单而有效的规则。
The only time it fails you is if you port between machines, and the xxx.h header includes, say, <pqr.h>
, but <pqr.h>
requires facilities that happen to be made available by a header <abc.h>
on the original platform (so <pqr.h>
includes <abc.h>
), but the facilities are not made available by <abc.h>
on the other platform (they are in def.h
instead, but <pqr.h>
does not include <def.h>
). This isn't a fault of the rule, and the problem is more easily diagnosed and fixed if you follow the rule.
它失败的唯一一次是如果您在机器之间移植,并且 xxx.h 标头包含,例如,,<pqr.h>
但<pqr.h>
需要恰好由<abc.h>
原始平台上的标头提供的功能(因此<pqr.h>
包含<abc.h>
),但这些功能不是通过提供<abc.h>
其他平台(他们是在def.h
代替,但<pqr.h>
不包括<def.h>
)。这不是规则的错误,如果您遵循规则,问题将更容易诊断和解决。
回答by yesraaj
Check the header file section in Google style guide
检查Google 样式指南中的头文件部分
回答by Rob Wells
Tom's answeris an excellent one!
汤姆的回答非常好!
Only thing I'd add is to never have "using declarations" in header files. They should only be allowed in implementation files, e.g. foo.cpp
.
我唯一要补充的是在头文件中永远不要有“使用声明”。它们应该只允许在实现文件中,例如foo.cpp
.
The logic for this is well described in the excellent book "Accelerated C++" (Amazon link- sanitised for script kiddie link nazis)
其逻辑在优秀书籍“Accelerated C++”(亚马逊链接- 为脚本小子链接纳粹消毒)中得到了很好的描述
回答by Steve Fallows
One more point in addition to the others here:
除了这里的其他点外,还有一点:
Don't include any private definitions in an include file. E.g. any definition that is only used in xxx.cpp should be in xxx.cpp, not xxx.h.
不要在包含文件中包含任何私有定义。例如,仅在 xxx.cpp 中使用的任何定义都应该在 xxx.cpp 中,而不是 xxx.h 中。
Seems obvious, but I see it frequently.
看起来很明显,但我经常看到它。
回答by Alex
I'd like to add one very good practice (both in C and C++) which is often forsaken :
我想添加一个经常被遗弃的非常好的实践(在 C 和 C++ 中):
foo.c
foo.c
#include "foo.h" // always the first directive
Any other needed headers should follow, then code. The point is that you almost always need that header for this compilation unit anyway and including it as a first directive warrants the header remains self-sufficient (if it is not, there will be errors). This is especially true for public headers.
应遵循任何其他需要的标头,然后编码。关键是你几乎总是需要这个编译单元的头文件,并且将它作为第一个指令包含保证头文件保持自给自足(如果不是,就会有错误)。对于公共标题尤其如此。
If at any point you need to put something before this header inclusion (except comments of course), then it is likely you're doing something wrong. Unless you really know what you are doing... which leads to another more crucial rule => comment your hacks !
如果在任何时候您需要在此标头包含之前放置一些内容(当然注释除外),那么您很可能做错了什么。除非你真的知道你在做什么......这会导致另一个更重要的规则=>评论你的黑客!