Pimpl (Opaque Pointers)

Summary

Pimpl is used to hide implementation details for library consumers. It hides headers, data members, as well as private functions.

// foo.h - header file
#include <memory>
class foo
{
  public:
    foo();
    ~foo(); 
    foo(foo&&);
    foo& operator=(foo&&);
  private:
    class impl;
    std::unique_ptr<impl> pimpl;
};
// foo.cpp - implementation file
class foo::impl
{
  public:
    void do_internal_work()
    {
      internal_data = 5;
    }
  private:
    int internal_data = 0;
};
foo::foo()
  : pimpl{std::make_unique<impl>()}
{
  pimpl->do_internal_work();
}
foo::~foo() = default;
foo::foo(foo&&) = default;
foo& foo::operator=(foo&&) = default;

Note that ~foo() has to be defined after foo::impl gets fulfilled. This is a requirement from unique_ptr:

std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the Pimpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr. (Conversely, std::shared_ptr can’t be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete).

Leave a Reply

Your email address will not be published. Required fields are marked *