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