当程序中涉及的类较多时,头文件中不恰当地包含冗余#include,会导致程序的编译时间增加。实时合理的使用前置声明来代替include可以很好的解决这个问题。
假设有两个类:class A和class B;那么class B的头文件中使用类A的不同情况可以选择选择 前置声明 和 #include“A.h”
1、使用前置声明的情况:
a. 以类A的指针或引用形式定义成员变量
b. 函数的返回值为类A或其指针(以引用做函数返回值的情况极少)
c. 函数的形参中涉及到类A
d. 定义list<A>, vector<A>等容器时,因为容器的初始容量是系统指定,所以不需要知道类A的大小,因此可以直接使用前置声明
e. 初始化类模板时,例如有个模板类C,利用类A初始化它并用指针来定义一个变量,例如C<A>* c;此时也可以模板类的前置声明和A的前置声明来说明
2、使用#include“A.h”的情况:
a. 成员变量直接定义为类A
b. 类B继承了类A
从上面的情况可以看出,大部分情况下头文件中使用前置声明即可以完成对头文件中所使用类的说明问题,就能满足编译工作,这样低耦合度的设计可以大大降低编译时间!
对于实现文件(.cpp)中,只要使用的相关类来完成功能的实现,就必须#include的来包含对应的头文件,除非其对应的头文件中已经include的过。不论是直接使用该类还是间接通过其他类调用实现,都必须#include相应的头文件。为此,自己编写了一个小的测试程序
//A.h
class A
{
public:
A();
~A();
public:
void OutPut();
};
//A.cpp
#include "A.H"
#include <iostream.h>
A::A()
{
};
A::~A()
{
};
void A::OutPut()
{
cout<<"iii"<<endl;
}
//B.h
class A;
class B
{
public:
B();
~B();
private:
A* a;
public:
A* GetA();
};
//B.cpp
#include "B.H"
#include "A.H"
B::B()
{
};
B::~B()
{
};
A* B::GetA()
{
return a;
}
//C.h
class B;
class C
{
public:
C();
~C();
private:
B* b;
static B* s;
public:
void test();
B* testb();
};
//C.cpp
#include "C.H"
#include "B.H"
#include "A.H"
C::C()
{
};
C::~C()
{
};
B* C::s = new B();
void C::test()
{
b->GetA()->OutPut();
}
B* C::testb()
{
return b;
}
void main()
{
C c;
c.test();
}
在C.cpp中的test()函数实现通过B的对象调用类B中的成员变量A来完成输出工作,因为B的头文件中是通过前置声明对涉及的A进行说明,所以在类C的实现中仅#include“B.H”是不够的,还必须#include "A.H",否则无法通过编译。
这样做也符合程序设计中所要求的“要显式包含所使用的类,不要间接包含头文件”【详见《大规模程序设计》】!