【Exceptional C++(15)】编译防火墙
2018-01-30 本文已影响22人
downdemo
- 如果类定义中的任何部分被改变,这个类的使用者必须重新编译代码,为了降低依赖性,一种常见技术是利用一个不透明指针隐藏一部分实现细节
class X {
...
private:
class XImpl* pimpl_;
};
- 可见类:客户代码所见并操控的类(即这里的X)
- pimpl:可见类隐藏在一个指针(pimpl_)下的类实现(XImpl)
- 这种方法的主要代价是性能
- 每个操作必须分配内存
- 每个隐藏成员需要一个额外的间接层来予以对其访问
- 应该放入XImpl的部分有四种常见的原则
- 全部私有数据:不错的开端,但可以做的更好
- 全部私有成员(包括函数):这几乎是最常用的用法,但对此有两个警告
- 但虚函数即使是私有的也不能放到pmpl中
- 如果pimpl中的函数要使用其他函数,可能需要一个指向可见对象的back pointer,这又增加了一层间接性,这个指针通常称为self_
- 全部私有成员和保护成员:这样更进一步的做法是错误的,保护成员不能放入pimpl。保护成员是为了让派生类看到并使用而存在的,如果派生类看不到的话等于对其弃之不用
- 使XImpl完全成为原来的X,将X编写为一个完全由简单的前置函数组成的公共接口:这只在少数几个有限情况下有用,好处是可以避免back pointer,但这样会使得可见类对继承来说全无用处
- XImpl通常需要一个指向X对象的back pointer,因为在pimpl中的函数也经常要调用可见类中的函数,通常要调用的函数是公有成员或虚函数