4.2 程序创建时间
对于给定的源文件,在它上面运行宏预处理程序后产生的代码称为翻译单元。创建一个C++(www.cppentry.com)程序的时间包括两部分:编译所有翻译单元所需要的时间和把这些翻译单元链接成一个可执行程序所需要的时间;其中实例化程序所用模板的时间包含在上面的编译时间和链接时间里面。在这一节里,我们给出了一些程序库实现者用于减少程序创建时间的技术。
4.2.1 编译时间
对于使用程序库中某些资源(如函数)的程序,减少它的编译时间的一个最简单的技术就是:最小化#include程序里面的代码。例如,假设我们的程序库给用户的窗口系统(window system)提供了一个接口,而且这个接口定义在程序库头文件Window_system.h里面:
- Windows_system.h :
- class Widget{
- //...
- };
- class Button : public Widget {
- //...
- };
- //程序库头文件中还有许多其他的类...
和大多数窗口系统的头文件一样,假设上面这个头文件也包含很多的代码(直接的代码和间接的代码),并且我们希望在自己程序库的头文件里面使用上面的Button类:- Ourlib.h:
- #include<Window_system.h>
- class Our_window {
- private:
- Button buttonl;
- Button button2;
- //...
- };
遗憾的是,如果以这种方式来实现我们的程序库,那么所有包含Ourlib.h头文件的翻译单元-甚至那些没有使用窗口系统的翻译单元一都将包含Window_system.h头文件,这将大大影响编译速度。解决的方法是:只声明类的名称(如Button),而不包含头文件,从而来提高编译速度:- Ourlib.h:
- Class Button; //取代 #include<Window_system.h>
- Class Our_window {
- Private:
- Button* buttonl;
- Button* button2;
- //...
- };
我们还必须相应地将buttonl和button2的类型从Button类型转变成Button*类型,于是现在对Button对象的所有存取操作都会通过一个间接层来进行,即要先寻找Button类的定义。因此,这种技术只是在编译时间和运行时间之间寻求平衡(这里减少了编译时间,增加了运行时间)。
有时候,我们可能会把这种技术推广到声明类以外的一些事物(如函数)。例如,假设Window_system.h包含以下create_buttons函数的声明,这个函数返回一个指针,指向新创建的包含n个Button对象的数组:
- Button* create_buttons(size_t n);
如果在Ourlib.h里调用create_buttons函数,我们就可以试着只声明create_buttons函数,而不包含Window_system.h:- Ourlib.h:
- //取代#include<window_system.h>
- class Button;
- Button* create_buttons(size_t n);
- Class Our_window {
- Public:
- Our_window() {
- buttonl=create_button(1);
- //...
- }
- //...
- private:
- Button* buttonl;
- //...
- };
上面的代码看起来非常地简单,但它可能包含了一个错误:传递给create_buttons的数字l是int类型,而不是函数声明中的size_t类型。如果Window_system.h还包含下面的声明:- Button* create_buttons(int n);
那么我们对create_buttons函数的调用就能解决上面的错误。如果Window_system.h现在并没有重载create_buttons函数,它也可以在以后的版本中重载这个函数,我们的代码也就只能在新版本中顺利通过编译。但由于以后重载的函数可能会改变代码实体,所以这个函数实现的功能或许将不再是我们原先希望的功能。为了避免这个问题,程序员应该只直接声明类的名称-而不能是函数-来取代包含头文件。