PIMPL 模式的實現及應用。

看一些開源庫,裏面好多類有一個**IMPL。經查詢還是有些門道和說法的。查詢了一些相關資料。(英文沒有翻譯,挺簡單的。)
PIMPL 也可以稱爲一種設計模式了。
現在摘錄如下:
pimpl 手法在 C++ 裏已是“高手”們廣泛運用的成熟方法之一,它的優點很多,諸如降低編譯依賴、提高重編譯速度之類的工具性優勢自不待贅言,而其對“保持接口穩定性”的優點更值得稱道。
It makes it possible to avoid other classes to know internal data structures and other information of the class. It also simplifies some #includepreprocessor instructions.避免別的class知道其內部的數據結構。還可以簡化預編譯指令。
下面是一個Example WITHOUT PIMPL 。
如下:
File foo.h
class CFoo
{
public:
    CFoo();
    ~CFoo();
    bool ProcessFile(const CString & csFile);
private:
    CFooInternalData    m_data;
    CHeader             m_header;
} 
File foo.cpp
 
#include "FooInternalData.h" 
#include "Header.h" 
#include "foo.h"
 
CFoo::CFoo()
{
}
 
CFoo::~CFoo()
{
}
 
bool CFoo::ProcessFile(const CString & csFile)
{
    //do something
    return true;
}
Main File
#include "FooInternalData.h"
 
#include "Header.h"
 
#include "foo.h"
 
 
int main()
{
    CFoo foo;
    foo.ProcessFile("c:\\data.bin");
    return 0;
} 
   The problem with this simple way of coding is that in your main file, you must include the foo.h to use it, but at the same time you must also include all needed files to allow the compiler to work correctly. In fact, the main does not need to include FooInternalData.h and Header.h (which are CFoo internal structures) except for compilation.... So with very big classes, you might do some huge includes and in this case, you can have some compiler or linker errors because files are already included elsewhere.
以上代碼有些不足:
第一,引入更多的頭文件降低編譯速度。而且這個聲明當然寫在一個頭文件裏,而頭文件,是不能預編譯或增量編譯的,如果你因此而引入一個諸如<windows.h>之類的頭文件,產生的代價可能是一杯咖啡的編譯時間--而且每次編譯都這樣;
第 二,大大提高的模塊的耦合度。在這裏,CFooInternalData從此與 CFoo緊緊綁定。在一個庫裏的模塊互相耦合當然可以忍受,不過你要記得,這裏有兩種耦合度:一個是編譯期的,一個是運行期的,這種方式下,無論編譯還是運行,它 們都耦合在一起,只要 CFooInternalData 發生變更,CFoo 的模塊也必須重新編譯;
第三,降低了接口的穩定程 度。接口的穩定,至少有兩個方面:一個是對於庫的運用,即方法調用不能變;一個是對於庫的編譯,即動態庫的變更最好能讓客戶程序不用重編譯。方法調用與這 個問題無關,但對於庫的編譯,如果CFooInternalData 變了,客戶程序顯然必須重新編譯,因爲 private 部分,雖然對於客戶程序不可用,但並不是不可見,尤其是對編譯器來說。對於一個動態鏈接庫,這個問題可能會讓人無法忍受。
pimpl 手法能比較完善的解決這些問題。利用 pimpl 手法,我們把數據細節隱藏到一個實現類裏:CFoo_pimpl,而 CFoo 的 private 部分只剩下一個指針,那就是傳說中滴 pimpl 指針
The Same Example with PIMPL

File foo.h
//here just declare the class PIMPL to compile. 
//As I use this class with a pointer, I can use this declaration 
class CFoo_pimpl; 
 
class CFoo
{
public:
    CFoo();
    ~CFoo();
    bool ProcessFile(const CString & csFile);
private:
    std::auto_ptr<CFoo_pimpl>    m_pImpl;
}  

File foo.cpp
#include "FooInternalData.h" 
#include "Header.h" 
#include "foo.h" 
 
//here defines PIMPl class, because it is use only in this file
class CFoo_pimpl()
{
public:
    CFoo_pimpl()
    {
    }
 
    ~CFoo_pimpl()
    {
    }  
    bool ProcessFile(const CString & csFile)
    {
        //do something
        return true;
    }
};
 
CFoo::CFoo()
:m_pImpl(new CFoo_pimpl())
{
}
 
CFoo::~CFoo()
{
    //do not have to delete, std::auto_ptr is very nice 
}
 
bool CFoo::ProcessFile(const CString & csFile)
{
    //just call your PIMPL function ;-)
    return m_pImpl->ProcessFile(csFile);
}
Main File
 #include "foo.h"
 
int main() 
{
    CFoo foo;
    foo.ProcessFile("c:\\data.bin");
    return 0; 
} 

The result is obvious: simplicity of use!! The main does not need more includes for internal structures of CFoo class.
Thus it is an excellent optimization to minimize linker and compiler errors.
Conclusion
It is a very simple and nice way for good coding!!! If you want to use classes in other projects, it does not introduce including difficulties.
Unfortunately, you must add some more code to type.
代碼來自:www.codeproject.com.http://www.cnblogs.com/kanego/archive/2011/11/23/2260700.html
本文版權歸作者 kanego 和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利.
發佈了11 篇原創文章 · 獲贊 6 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章