【C++】Pimpl机制
1.问题
- 隐藏实现
我们在给客户端提供接口时只希望暴露它的接口,而隐藏它的实现或者算法。 - 重新编译
当一个工程很大的时候,对于底层的头文件是不希望被修改的,因为这会导致包含该头文件的所有源文件都要重新编译。
2.Pimpl简介
Pimpl的字面解释:
- Private Implementation
直译就是“实现私有化”。将实现私有化,使得头文件对改变不透明,解开类的使用接口和实现的耦合。 - pointer to implementation
“指向实现的指针”,这种说法更关注代码的实现方法,即创建一个opaque pointer指针,用以隐藏private成员。
Pimpl的思想是把类的公有使用接口与所有关于类的私有化实现分离。由于其他类使用该类的接口需要依赖类的头文件,头文件中任何变化都会影响到其他类,即使仅仅是对private或protected进行修改。Pimpl机制可以用来减少因private(protected)修改造成重新编译的代价。
3.Pimpl具体分析
在Pimpl机制中,我们在主类的private中添加一个pimpl类,如下:
1. //TestClass.h
2. class TestClassImpl; //前置声明
3. class TestClass{
4. public:
5. TestClass();
6. ~TestClass();
7. void func();
8. private:
9. TestClassImpl *class_pimpl_;
10. };
TestClass提供一个公有接口,除非修改这个公有接口,否则这个头文件是不会被修改的。然后,利用pimpl类来完成主类的细节实现。在主类构造函数中,就需要完成pimpl类指针的实例化:
1. //TestClass.cpp
2. class TestClassImpl{
3. public:
4. void func(){
5. //实现细节
6. func1();
7. }
8. void func1(){
9. .........
10. }
11. };
12.
13. TestClass::TestClass():class_pimpl_(new TestClassImpl){}
14.
15. TestClass::~TestClass(){
16. delete class_pimpl_;
17. }
18.
19. void TestClass::func(){
20. class_pimpl_->func();
21. }
现在,已经很容易看出在Pimpl机制中,对实现类(pimpl类)随意地进行增删和修改,都不会影响到TestClass.h文件。而包含TestClass.h的源文件也不需要重新编译。
当然,在性能上的开销会增加。对每个构造和析构函数,需要分配内存,需要对实现类指针进行管理。