【C/C++程序設(shè)計(jì)技巧】Pimpl機(jī)制

作者:學(xué)到牛牛任金城,歡迎關(guān)注公眾號【學(xué)到牛?!?。
更多入門到精通課件、資料聯(lián)系作者君或參看這里:學(xué)到牛牛?www.xuedaon.com
我們平時在編寫C/C++程序時我們都會在源文件(后綴為.c或.cpp的文件)中包含頭文件,當(dāng)頭文件內(nèi)容發(fā)生改變時,包含其的源文件在編譯時也需要重新編譯,也就是現(xiàn)在假如有如下關(guān)系圖:

這里的N個cpp文件都包含了A.h,當(dāng)每次修改A.h內(nèi)容,再次編譯時這里的N個cpp文件無論內(nèi)容是否改變都將重新編譯!這時就好比是牽一發(fā)而動全身,會導(dǎo)致編譯效率低下;
那么該如何解決呢?也就是如何才能做到既能兼顧頭文件內(nèi)容的可擴(kuò)展兼容性,又能去掉那些重復(fù)無效的編譯(編譯那些無需再次編譯的源文件即內(nèi)容并未發(fā)生改變的源文件)。這就是我們今天的主角——PIMPL機(jī)制(一種利用指針實(shí)現(xiàn)的數(shù)據(jù)私有化可擴(kuò)展兼容機(jī)制)。我們先來看一個沒有引入PIMPL機(jī)制的情況,測試代碼如下:
我們再編寫一個Makefile文件來模擬IDE的編譯過程:
當(dāng)我們執(zhí)行make時效果如下:

此時若我們沒做任何文件修改若直接再次執(zhí)行make效果則會是:

當(dāng)我們將頭文件person.h中注釋的測試成員取消注釋:

后再執(zhí)行make的效果:

此時我們會發(fā)現(xiàn)所有的.cpp源文件又都重新被編譯,但他們都未做任何更改,那這些編譯目前來說都是無效的沒有必要的編譯,這里增加的屬性就好比是針對于windows環(huán)境做出的調(diào)整改變,本質(zhì)對當(dāng)前環(huán)境是沒有任何影響的,當(dāng)前環(huán)境下也不需要去關(guān)心這個變化,但是它卻影響了當(dāng)前環(huán)境下的編譯,這樣肯定是不太好的,所以我們就可以利用PIMPL機(jī)制來改進(jìn),即在原類對象中提供一個用于存儲數(shù)據(jù)的私有對象指針,將類對象中原有的私有數(shù)據(jù)成員放入在源文件在定義的私有對象中還可以定義相關(guān)訪問接口便于原對象調(diào)用,具體簡單改進(jìn)后代碼如下:
此時當(dāng)我們第一次執(zhí)行make時效果與之前一樣會編譯所有源文件:

但當(dāng)我們在私有數(shù)據(jù)對象中改變時(將現(xiàn)在PrivatePersonData中int m_addTest;注釋去除)再make時的效果:

此時我們可以看出與修改后無關(guān)聯(lián)的源代碼(man.cpp與xuedaon.cpp)并沒有再次重新編譯,這樣就既能兼顧頭文件內(nèi)容的可擴(kuò)展兼容性,又能去掉那些重復(fù)無效的編譯,并且還相當(dāng)于對外隱藏了Person類中原有的數(shù)據(jù)成員,防止代碼的盜用;在Qt中就是利用在源文件中定義私有對象配合定義Q_DECLARE_PRIVATE(定義獲取私有對象的指針的接口函數(shù)和聲明私有對象)與Q_D宏定義(調(diào)用接口獲取私有對象的指針)實(shí)現(xiàn)的PIPML機(jī)制,有興趣的可以看看下面的源代碼:
希望上面的介紹能對大家理解PIMPL機(jī)制有所幫助!祝大家在學(xué)習(xí)的道路上能更上一層樓。