C++中句柄类小结

来源:互联网 发布:openwrt python 编辑:程序博客网 时间:2024/05/18 05:45

句柄类,也就是handle class,是C++中的一种重要的面向对象方法,其作用有两条:1. 减少头文件的编译依赖关系,让文件间的编译更加独立;2. 增加系统安全性,把类的实现细节和声明完全的分离开,让类的实现细节对于用户完全的不可见,增加信息的安全性。

 

句柄类实际我在很多代码中都见过,一些标准化的代码几乎全都用句柄类来实现,而原因正是以上两条。在一些大型的系统中,编译源文件的代价往往非常大,特别是一些核心文件,往往很小的代码改动就能引起整个系统的重新编译,由于系统存在诸多的包含依赖关系,因此编译的过程中会先去检测外部包含文件是否改动,而外部包含文件如果仍然存在外部包含,那编译器就会继续检测,直到检测不到为止,这个过程往往非常的漫长,而编译却是系统开发中最普遍的行为之一,因此,编译的低效率可以直接导致系统开发的低效率,所以说,提高编译效率对于系统开发来说非常有意义。想改善这种状况,就要降低源文件的包含依赖性,而想降低源文件依赖性,最直接的方法就是减少头文件的包含,也就是在头文件中减少#include的使用,而改用类前置声明,这要求开发者在类中不能定义实体,只能定义指针,而如果要用到类中方法的话,则可以在实现文件中(大多数情况是CPP文件),包含特定的类即可,这种做法在代码层面上来看就是:头文件全部都是类的前置声明,而CPP文件里则会有部分include代码的存在。这么做就达到了增加编译效率的目的,比如说三个类A、B、C,三个类存在这样的依赖关系:A包含B,B包含C,如果按照传统的方法,如果C中改动了一个数据成员,那么A和B全部都需要重新编译,那么编译的代价就是对A、B、C三个文件全部重新编译,那么如果改用句柄类,那么C的改动,就引起不了A和B的重新编译,因为A和B只包含了C的前置声明,而没有包含C的类定义,因此重编译的代价仅仅是一个文件而已。

 

这种方式的另一个好处是实现了类数据成员和函数接口的完全分离,增加了系统的安全性,很多人有个误解,认为类的数据成员属于类声明的部分,而不是类实现,这是错的,实际上一个数据成员建立,会在无形中调用构造方法、设置内存等等,只不过这些东西都是编译器做的,程序员看不到而已。在一些完全的面向对象语言里(比如JAVA),类的实现和类的声明是完全分离的,虽然用户有时候会把类的数据成员和数据方法定义到一块,但是编译器却并不会直接在类的主体中直接定义实体,而仅仅是定义了一个地址而已,而在实现部分,才会分配实体的内存。而在C++中如果想这么做,就需要句柄类的帮忙,也就是把一个类拆分成两个类,一个负责数据成员,一个负责数据方法,数据成员类只提供基本的数据和基本的数据操作函数,而数据方法则提供真正的用户接口。我在阅读QWT源代码的时候,看到了一种非常好的实现句柄类的方法,QWT中,把数据类定义成了句柄类的内部类,而数据成员声明成了public,虽然是这样,但是却并不会影响数据的安全性,因为内部与的作用域仅仅在外部类内部而已,这样的话,就既实现了句柄类对数据的控制,又实现了函数接口和数据的分离。