PIMPL 是 C++ 中的一個編程技巧,意思為指向實現的指針。具體操作是把類的實現細節放到一個單獨的類中,并用一個指針進行訪問。
二進制兼容是指當庫文件升級后所有使用該庫的應用程序不必重新編譯,其本質就是類的內存布局不變。使用 pimpl 方法設計類可以實現二進制兼容的目的。
原始類定義:
class demoClass{private: int a; int b;};
內存布局如下:
類更改后的定義:
class demoClass{private: char c; int a; int b;};
內存布局如下:
class demoClass{private: class demoClassImpl; demoClassImpl* impl;};class demoClass::demoClassImpl{public: int a; int b;};
內存布局如下:
如上圖所示,無論類的實現類的數據成員如何變化,類的布局始終不變。
作為接口的提供者,我們希望接口的使用者不必知道接口實現的更多細節,因為根據類的私有數據成員和方法一般就可以猜測出接口的設計方式。
通過 pimp 方法設計類可以實現隱藏類的私有成員和方法的目的,僅對外暴露公有的接口。
class demoClass{public: void func();//對外接口private: class demoClassImpl; demoClassImpl* impl;};class demoClass::demoClassImpl{private: int a; int b; void func1(); void func2();public: void func();};void demoClass::func(){ impl->func();}
在一個常用的頭文件中如果包含了太多其他不必要的頭文件會嚴重降低編譯效率。
值類型的成員因為要分配內存大小必須知道其確定的定義,需要包含其頭文件
#include "A.h"class demoClass{ A a;};
如果僅有類的申明則會出錯:
class A;class demoClass{ A a;};
class A;class demoClass{ A func(A a);};
一般庫文件使用者僅需要包含當前庫對應的頭文件即可,不應該再包含其他的頭文件。假設庫的頭文件定義如下:
#include "A.h"class demoClass{private: A a;public: void func();};
此時,若 A 為另外一個公共庫,則庫的使用者需要在項目中配置 A.h 的路徑;若 A 為自定義類,則庫的提供者還需要額外提供 A.h 文件。
使用 pimpl 方法改進則可以減少編譯依賴,僅在類的實現文件中包含頭文件即可:
// demoClass.hclass demoClass{public: void func();//對外接口private: class demoClassImpl; demoClassImpl* impl;};// demoClass.cpp#include "A.h"class demoClass::demoClassImpl{private: A a;public: void func();};
使用 pimpl 的方式把類的功能實現用另外一個獨立的類來完成,可以在需要的時候動態的配置類的實現方法,而保持類的接口不變。
公共接口類:
class demoClassImpl;class demoClass{public: void func();//對外接口public: demoClassImpl* impl;};void demoClass::func(){ impl->func();}
功能實現抽象類:
class demoClassImpl{public: virtual void func() = 0;};
功能實現派生類:
class demoClassImpl1 : public demoClassImpl{public: void func() { cout << "實現方式1" << endl; }};class demoClassImpl2 : public demoClassImpl{public: void func() { cout << "實現方式2" << endl; }};
功能實現方式的動態配置:
demoClass* demo = new demoClass;demoClassImpl1* impl1 = new demoClassImpl1;demo->impl = impl1;demo->func();demoClassImpl2* impl2 = new demoClassImpl2;demo->impl = impl2;demo->func();
本文鏈接:http://www.www897cc.com/showinfo-26-70407-0.htmlC++ 慣用法之 PIMPL
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 十個React狀態管理庫推薦:打造高效、可維護的前端應用
下一篇: 探秘C++的移動語義:釋放力量,提升性能