tza*_*man 68
通常,您只想将最小必要包含放入类头文件中,因为使用该标头的任何其他人也将被强制使用#include
它们.在较大的项目中,这会导致构建速度降低,依赖性问题以及各种其他肮脏问题.
可以将头文件视为类的公共接口.你不想鞍大家谁用额外的依赖使用它,除非他们是必要的,以便能够使用类.
将类实现中仅需要的任何内容移动到源文件中.对于标题中使用的其他类,#include
如果您确实需要知道标题中的大小或内容,则只有标题 - 其他任何内容和前向声明就足够了.大多数情况下,您只需要#include
继承自的类,以及其对象是您的类的值成员的类.
这个页面有一个很好的总结.(以下复制供参考)
大型软件项目即使在C语言编程时也需要仔细的头文件管理.当开发人员转向C++时,头文件管理变得更加复杂和耗时.这里我们提供一些头文件包含模式,这将简化这项工作.
在这里,我们讨论简化头文件管理所需的C++头文件包含的基本规则.
只有在前向声明不能完成工作时才应包含头文件.头文件的设计应使头文件包含的顺序不重要.这是通过确保它x.h
是第一个头文件来实现的x.cpp
.头文件包含机制应该容忍重复头文件包含.以下部分将借助示例解释这些规则.
以下示例说明了不同类型的依赖项.假设A类的代码存储在a.cpp
和中a.h
.
a.h
#ifndef _a_h_included_
#define _a_h_included_
#include "abase.h"
#include "b.h"
// Forward Declarations
class C;
class D;
class A : public ABase
{
B m_b;
C *m_c;
D *m_d;
public:
void SetC(C *c);
C *GetC() const;
void ModifyD(D *d);
};
#endif
Run Code Online (Sandbox Code Playgroud)
a.cpp
#include "a.h"
#include "d.h"
void A::SetC(C* c)
{
m_c = c;
}
C* A::GetC() const
{
return m_c;
}
void A::ModifyD(D* d)
{
d->SetX(0);
d->SetY(0);
m_d = d;
}
Run Code Online (Sandbox Code Playgroud)
让分析头文件夹杂物,从所涉及的本实施例中的类点,即ABase
,A
,B
,C
和D
.
ABase
是基类,因此需要类声明来完成类声明.编译器需要知道大小ABase
以确定总大小A
.在这种情况下abase.h
应明确包括在内a.h
.A
包含Class B
by value,因此需要类声明来完成类声明.编译器需要知道B的大小来确定总大小A
.在这种情况下b.h
应明确包括在内a.h
.Class C
仅包含在指针引用中.大小或实际内容C
对a.h
或不重要a.cpp
.因此,只包含了前瞻性声明a.h
.请注意,c.h
未包含在a.h
或中a.cpp
.D
仅用作指针引用a.h
.因此,前瞻性声明就足够了.但在实质上a.cpp
使用类D
,所以它明确包括d.h
.只有在前向声明不能完成工作时才应包含头文件.通过不包括c.h
和d.h
类的其他客户端A
永远不必担心c.h
,d.h
除非他们按值使用C类和D类.
a.h
已被列为第一个头文件.a.cpp
这将确保a.h
不希望之前包含某些头文件a.h
.由于a.h
已作为第一个文件包含在内,因此成功编译a.cpp
将确保a.h
不会期望之前包含任何其他头文件a.h
.如果对所有类都遵循,(即x.cpp
始终包括x.h
作为第一个头),则不依赖于头文件包含.
a.h
包括检查符号的预处理器定义_a_h_included_
.这使得它能够容忍重复的内含物a.h
.
类X
和Y
以下示例之间存在循环依赖关系.通过使用前向声明来处理此依赖项.
x.h and y.h
/* ====== x.h ====== */
// Forward declaration of Y for cyclic dependency
class Y;
class X
{
Y *m_y;
...
};
/* ====== y.h ====== */
// Forward declaration of X for cyclic dependency
class X;
class Y
{
X *m_x;
...
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34612 次 |
最近记录: |