Pimpl is a common pattern in C++ design. It hides a class implementation details and keeps the public/protected interface unchanged when the implementation is changed.
Following codes illustrate how Pimpl pattern is implemented
// a.h class A { public: A(); ~A(); public: void foo(); // public/protected interfaces private: class Pimpl; // partial (forward declare) friend class Pimpl; Pimpl* self; // opaque pointer // hold all private member/method };
The implementation:
// a.cpp #include "a.h" // private implementation is declared in a.cpp only, // changing a.cpp without a.h won't require re-compiling // modules that reference a.h class A::Pimpl { friend class A; private: Pimpl() {} ~Pimpl() {} void foo() {} // implementation of foo() private: int props; // private members of A }; A::A() : self(new Pimpl()) { } A::~A() { delete self; } void A::foo() { self.foo(); }
When smart pointer is used, the code is changed like this
// a.h A(); class Pimpl; std::unique<Pimpl> self; // a.cpp A::A() : self(new Pimpl()) {}
It wishes Pimpl* object is deleted automatically by smart pointer, so A::~A is not needed. Unfortunately, such code can not get compiled. Because A::Pimpl* is an opaque pointer (partial declared class) outside of a.cpp, it can NOT be created nor deleted outside of a.cpp.
Here is the proper implementation
// a.h A(); ~A(); // do NOT declare as ~A() {} class Pimpl; std::unique<Pimpl> self; // a.cpp A::A() : self(new Pimpl()) {} A::~A() {} // or in C++11 A::~A = default;
Because A::~A is defined in a.cpp, the compiler knows how to delete Pimpl* object.