-
使用pimpl将实现细节移出头文件。
-
将私有成员变量和私有方法移入Impl类,可以实现数据和方法的封装,以避免在公开头文件中声明私有方法。
-
不能在实现类中隐藏虚方法(virtual method),虚方法必须在公开类中出现以便由继承类重载。
-
可以在实现类中加入指向公开类的指针,以便于Impl类调用公开方法。或者也可以将公开类传给需要它的实现类方法。
-
与Bridge Pattern的区别:The Bridge pattern is about object-oriented design, while the PIMPL idiom is about physical design of files.
-
解释:
But in its basic and common form, a class using PIMPL points to a single implementation, so there is no abstract class with distinct subclasses — just one class, forward declared, and compiled elsewhere. Changing the implementation class does not require any recompilation of sources that include the main header.
For example, say you have a lot of private member functions, private enums, and private data. And these private "bits" change fairly frequently as the class is developed and maintained. If the #include dependencies are such that touching this header file causes a large number of sources to be recompiled, you have a good candidate for PIMPL.
-
部署pimpl的方法:Making Pimpl Easy
AutoTimer.h
#include <boost/shared_ptr.hpp> class AutoTimer { public: /// Create a new timer object with a human readable name AutoTimer(const std::string &name); /// On destruction, the timer reports how long it was alive ~AutoTimer(); private: // Make this object be noncopyable because it holds a pointer AutoTimer(const AutoTimer &); const AutoTimer &operator =(const AutoTimer &); class Impl; boost::shared_ptr<Impl> mImpl; };
AutoTimer.cpp
#include "StdAfx.h" #include "AutoTimer.h" #include <iostream> #include <windows.h> #include <string> class AutoTimer::Impl { public: double GetElapsed() const { return (GetTickCount()-mStartTime) / 1e3; } std::string mName; DWORD mStartTime; }; AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName = name; mImpl->mStartTime = GetTickCount(); } AutoTimer::~AutoTimer(void) { std::cout<<mImpl->mName<< ": took " << mImpl->GetElapsed() << " secs" << std::endl; }
Main.cpp
#include "stdafx.h" #include "AutoTimer.h" #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { AutoTimer timer("MyTimer"); for (int i = 0; i < 10000; ++i) { cout << "."; } cout << endl; return 0; }