今天在写代码时,遇到了是否需要加头文件的问题,看到这个博客之后收益匪浅,因此转载该篇文章。
转载:https://www.jianshu.com/p/9768175387b6
首先我们看这样一个示例程序:
以上代码中,类CY中有个CX类型的数据成员,我们需要在CY.h中包含CX.h才能编译通过。所以,我们说这里的CY类依赖CX类,当CX.h修改导致CX对象的大小发生变化时(比如,新增一个数据成员或新增一个方法时), CY.cpp都需要重新编译。这在大型工程中可能会造成巨大的编译成本.
有没有办法解决这个问题? 有!使用类前置声明。
我们先看看修改之后的代码。
这里首先将CX.h的包含语句修改为CX的类前置声明,然后数据成员由CX对象修改为指向CX对象的指针。但是奇怪的是,如果不将CX对象修改为指向CX对象的指针,还是会编译出错。
error C2079: “CY::m_x2”使用未定义的 class“CX”
只能在指针或引用类型上使用类前置声明
当CY.h中的数据成员是CX对象时,CY.h需要知道CX对象的大小,当CX.h发生修改,例如向CX类添加数据成员或者方法成员,CX对象大小发生改变,所以CY.cpp必须重新编译。
当CY.h中的数据成员是指向CX对象的指针时,CY.h并不需要知道CX对象的大小,因为指向CX对象的指针在给定平台上的大小是固定的。所以,只需要一种“非完整性声明”,也即这里的类前置声明。
引用的本质还是指针,所以类前置声明也适合引用的情况。
可以使用类前置声明的几种情况
1. CY有一个类型为指向CX的指针的成员变量。
2. CY有一个类型为容器成员,且容器类的元素是指向CX的指针。但是如果元素是CX对象的话,则会编译出错,原因是CY需要知道CX对象的大小。
3. CY中有一个函数,它的返回值是CX对象/指向CX的指针/指向CX的引用,或者它的参数是CX对象/指向CX的指针/指向CX的引用。
总结
合理的使用类前置声明,不仅可以减少工程编译的时间,更重要的是,可以让你从更深的视角洞察工程的物理依赖关系,从而为代码重构提供依据。在写代码的时候,不妨经常问一下自己:我是否真的有必要在这个头文件里包含另一个头文件?