总的一条就是让client只依赖“名字”,而不依赖任何"实现"。
“实现” 具体的就是2类
1)函数体,code
2)任何内存块大小,layout细节
为什么会有二进制兼容问题,就是因为一般的c++头文件并不是单纯的接口声明,其中也还包括了“实现细节”,因为成员变量就是一种内存layout,就属于实现细节。对于函数,也有2种情况使得client依赖了实现:
1)inline function: 直接让client依赖了code
2)virtual 函数:隐含的vtable 实际也是让client 依赖了某种内存layout
著名的Pimpl模式就是针对c++这种情况量身定制的二进制兼容方案
1)只定义非inline,非virtual的 public函数
2)成员变量只有一个 Impl*, 虽然client也依赖了这一实现细节,但它的内存块layout和大小都不会变。