C++类中使用前置声明和使用include包含头文件的感想

时间:2022-07-20 23:50:44

两者优缺点

前置声明,可以减少依赖,减少暴露,但是大部分需要在构造函数里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头文件

  1. ClassA的数据成员为ClassB的对象
  2. ClassA派生自ClassB
  3. ClassA的函数具有ClassB类型的参数
  4. ClassA的函数使用ClassB的静态成员
  5. ClassA向ClassB发送消息(比如信号)

  6. (来源于《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

看到这里点个赞呗!