65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PIMPL 设计模式

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.77/5 (16投票s)

2007 年 2 月 6 日

CPOL

1分钟阅读

viewsIcon

88781

解释为什么以及如何使用 PIMPL。

引言

PIMPL(私有实现)是一种简单的方法,可以将类的部分实现细节对同一项目的其他类隐藏起来。

这使得其他类无需了解类的内部数据结构和其他信息。它也简化了一些#include预处理器指令。

不使用 PIMPL 的示例

我们有一个CFoo类,它定义在两个文件中foo.hfoo.cpp

我们的main实例化这个类来运行它的一个函数。

文件 foo.h

class CFoo
{
public:
    CFoo();
    ~CFoo();
    bool ProcessFile(const CString & csFile);
private:
    CFooInternalData    m_data;
    CHeader             m_header;
} 

文件 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;
}

主文件

#include "FooInternalData.h"
#include "Header.h"
#include "foo.h"

int main()
{
    CFoo foo;
    foo.ProcessFile("c:\\data.bin");
    return 0;
} 

这种简单编码方式的问题在于,在你的主文件中,你必须包含foo.h才能使用它,但同时你还必须包含所有必要的头文件,以允许编译器正确工作。实际上,main不需要包含FooInternalData.hHeader.h(这些是CFoo的内部结构),除了编译之外……因此,对于非常大的类,你可能会进行大量的包含,在这种情况下,你可能会遇到编译器或链接器错误,因为文件已经在其他地方包含过了。

使用 PIMPL 的相同示例

文件 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;
}  

文件 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);
}

主文件

#include "foo.h"
int main() 
{
    CFoo foo;
    foo.ProcessFile("c:\\data.bin");
    return 0; 
} 

结果显而易见:使用起来更简单!主文件不需要为CFoo类的内部结构包含更多的头文件。

因此,这是一个最小化链接器和编译器错误的绝佳优化。

结论

这是一种非常简单且良好的编码方式!如果你想在其他项目中使用类,它不会引入包含的困难。

不幸的是,你必须添加一些额外的代码来输入。

历史

  • 2007 年 2 月 6 日:初始发布
© . All rights reserved.