之前看到喵哥在知乎上回答了一個設計模式的問題,其中介紹了pimpl模式(Private Implementation,顧名思義,將實現(xiàn)私有化,力圖使得頭文件對改變不透明)?!边@個和qt里面的d-pointer用法應該是一致的“,我也給喵哥做了個小回復。
這是喵哥問題的截圖:
下面我也來分享一下自己平時使用的d-pointer用法。
歡迎關(guān)注微信公眾號:羽林君,或者添加作者個人微信:become_me
喵哥的回答介紹
//?MyClass.h
class?MyClass?{
public:
????void?func1();
????void?func2();
private:
????class?impl;
????impl*?pimpl;
};
//?MyClass.cc
class?MyClass::impl?{
public:
????void?func1();
????void?func2();
private:
????void?func3();
????void?func4();
????int?a;
????int?b;
};
MyClass::MyClass()?{
????pimpl?=?new?impl;
}
void?MyClass::func1()?{
????pimpl->func1();
}
將類的private屬性隱藏進一個內(nèi)部類,然后通過一個指針訪問(提前聲明)它的接口。在頭文件中只
暴露出應該暴露的功能,然后持有一個Impl的指針,而Impl則具體在http://MyClass.cc中定義,
用戶什么都看不到。然后所有的功能都通過Impl完成。頭文件里的Impl的指針也可以通過智能指針(u
nique_ptr)來代替,但這不是本文的重點。再總結(jié)一下pimpl模式的優(yōu)點:
非常適合隱藏private實現(xiàn):如果想要在頭文件中暴露public接口,但又不想暴露private實現(xiàn)的細節(jié),則可以使用pimpl模式來隱藏細節(jié)。
pimpl模式也被稱為編譯防火墻,是一種用來減少編譯時間的方法。通常來講,如果頭文件里的某些內(nèi)容變更了,意味著所有引用該頭文件的代碼都要被重新編譯,即使變更的是無法被用戶類訪問的私有成員。將這部分代碼從被引用多次的頭文件里移除到只被引用編譯一次的源文件中,更改此文件就不會付出太長的編譯時間。
作者:程序喵大人
鏈接:https://www.zhihu.com/question/340301316/answer/2264148507
個人的一些使用補充:
喵哥介紹的已經(jīng)很詳細了,寫了一個demo,還把pimpl模式優(yōu)點給大家介紹了,我就不多做贅述了。
但是我想給大家分享一種我自己實際使用的 d-pointer方法,有些區(qū)別,但是這種模式下的變種,分享給大家,希望可以對大家有些幫助。
Pimpl或者d-pointer機制其實這是橋接模式的一種組合使用。通過在新的類定義使用其他類,我們可以對實現(xiàn)某個功能類隨意的進行增刪和修改,
不過Pimpl也有些缺點:例如,每次函數(shù)調(diào)用都涉及到指針操作,程序運行速度可能變慢;此外也需要在堆上開辟空間,記得使用完之后 delete,一般也建議使用智能指針定義。
d-pointer和Pimpl使用組建上都是差不多的,我們會定義一個類或者結(jié)構(gòu)體,然后再在使用的類中進行 定義該類的指針變量,在使用時候 new。
按理說都差不多情況下,選擇一種就好了,為什么還要介紹 d-pointer呢,因為Pimpl有些場景沒法一起共存使用,例如我定義的impl類功能十分龐雜,我想把它定義為一個單獨的文件,這個時候pimpl就不太好使用了。因為pimpl模式下,被橋接使用的類屬于最外層類的一個類成員,我們對該被橋接類的定義都被括在該文件下。而d-pointer使用中,被橋接類只要在文件最前面申明一下就好。其他的使用方式是和pimpl沒有區(qū)別的。
下面是我使用的示例demo:
test_pimpl.hpp
#pragma?once
#include?<iostream>
class?impl{
?public:
????impl(){}
????~impl(){}
??void?func1(){
???std::cout<<__FUNCTION__<<"?target?"<<std::endl;
??}
??void?func2(){}
?private:
??void?func3(){}
??void?func4(){}
??int?a;
??int?b;
};
pimpl_bridge.h
#pragma?once
class?impl; //pimpl模式在類內(nèi)部定義
class?MyClass?{
?public:
??MyClass();
??void?func1();
??void?func2();
?private:
??impl*?pimpl;
};
main.cpp
#include?<iostream>
#include?"test_pimpl.hpp"
#include?"pimpl_bridge.h"
MyClass::MyClass()?{
?pimpl?=?new?impl();
}
void?MyClass::func1()?{
?pimpl->func1();
}
int?main()
{?
?MyClass?test;
?test.func1();
}
結(jié)語
這就是我自己的一些設計模式的使用分享。如果大家有更好的想法和需求,也歡迎大家加我好友交流分享哈。
作者:良知猶存,白天努力工作,晚上原創(chuàng)公號號主。公眾號內(nèi)容除了技術(shù)還有些人生感悟,一個認真輸出內(nèi)容的職場老司機,也是一個技術(shù)之外豐富生活的人,攝影、音樂 and 籃球。關(guān)注我,與我一起同行。