Minimize compilation dependencies between files
动机
这个问题主要是在多文件的程序中,如果某个class实现文件做了些许的修改,当你重新build/make这个项目时,可能所有相关依赖的文件都重新编译和链接了。这个就是“接口和实现没有很好分离的一大弊端”。
考虑这样一个程序:
1 | //可能包含的头文件 |
这里的问题是:在private中的那几个变量定义,我们需要找到Date和Address的具体定义,也就是说一旦这个文件依赖的头文件发生了变化,那么Person class也要重新编译。
解决方法
当然,我们可以分离声明和定义,比如在刚刚那个文件中声明:
1 | class Date; |
但这里的问题是,对于前置声明,编译器必须提前知道对象的大小,这样才能在stack中分配足够大的空间。
借鉴Java的经验,我们用一个指针去指向需要的对象。例如:
1 |
|
这种设计就叫做——pointer to implementation。至此,Person的客户端就与其他class包括Person的实现细节分离了,也就是其他类的修改不会影响到Person客户端重新编译。
制作一个handle class
通常来说,我们应该为声明式和定义式提供不同的头文件,这样就不用每次都前置声明其他的class。
制作一个handle class的方法有两种,第一种已经在前面提及过了,至于第二种就是构造一个抽象类:
1 | class Person{ |
当然,由于这是abstract class,我们需要一个concrete class来定义所有的函数。
建议
- 为了保证编译依赖最小化,我们应该依赖于声明而不是定义。这里有两个实现手段——handle class和interface class;
- 程序库头文件应该以“完整的并且是仅有声明”的形式存在;