两者优缺点
前置声明,可以减少依赖,减少暴露,但是大部分需要在构造函数里new一个实例,在析构函数里再delete掉,然后还要检测实例是否为空。
包含头文件,比较简单,甚至可以不要写显式的构造和析构函数。但是会增加依赖和暴露。
当两个类相互包含时,不能使用include包含头文件。
为什么要使用前置声明
假设有一个Date类
Task1.h
class Date {
private:
int year, month, day;
};
Task2.h
#include "Date.h"
class Task2 { public: Date getData(); };
一个采用前置声明,一个采用#include
有些情况不能用前置声明代替#include
比如Task1.h改成
class Date;
class Task1 {
public:
Date d;
};
会编译错误,因为Date d定义了一个Date类型变量,编译器为d分配内存空间的时候必须知道d的大小,必须包含定义Date类的Date.h文件。
这是可以采用指针来代替
class Date;
class Task1 {
public:
Date *d;
};
指针的大小是固定的。在32位机上是4字节,64位机上是8字节。这时编译Task1的时候不需要Date的大小,所以和Date的定义无关。
哪些情况下类A需要包含类B头文件
- ClassA的数据成员为ClassB的对象
- ClassA派生自ClassB
- ClassA的函数具有ClassB类型的参数
- ClassA的函数使用ClassB的静态成员
- ClassA向ClassB发送消息(比如信号)
-
(来源于《C++Qt设计模式》P166,书上说必须在ClassA的实现文件中包含指令#include ClassB,但是我觉得在头文件中也必须包含指令#include ClassB,具体可以使用代码测试一下,这里在后续使用中再试试)
有一篇文章讲何时可以用前置声明代替#include
http://blog.csdn.net/rogeryi/article/details/1439597
上述例子可以说明
如果使用object reference 或 object point 可以完成任务,就不要用object
这样可以尽最大可能避免#include
为声明式和定义是提供不同的头文件
在函数库的设计过程中,接口的设计就要遵循上述准则。
一个接口的头文件是这样的
class Date;
class Address;
class Email;
Date getDate();
如果客户只用到Date类,编译器就只会去编译Date.h,而不去编译Address.h,Email.h 等等文件
总结
ClassA需不需要包含ClassB的头文件,应该是取决于ClassA的头文件是否涉及需要知道ClassB的大小,以分配空间。
参考文章
http://blog.csdn.net/fjb2080/article/details/5533514
http://blog.csdn.net/fallStones/article/details/6266632
看到这里点个赞呗!