Tutoriale

The PIMPL idiom

By on 14/01/2017

The purpose

Remove compilation dependencies on internal class implementations and improve compile times.

The story behind

When a header file changes, any files that #include that file will need to be recompiled. In the case of a class header, this is true even if those changes only apply to private members of the class. The PIMPL idiom hides private members from any users of the header file, allowing these internal details to change without requiring recompilation of the client code.

Lines 5–17 define a class, foo, to which we have applied the PIMPL idiom. This class definition includes only the public interface of the class and a pointer to the internal implementation. We use a std::unique_ptr (line 16) to ensure the lifetime of the implementation is managed correctly, which we initialise in foos constructor (line 35).

While the internal implementation class, impl, is declared in the header file on line 15, its definition appears in the implementation file on lines 22–32. This allows the class definition to change without requiring users of foo to recompile.

We have explicitly defaulted foo’s destructor on line 40, which is necessary because the destructor needs to be able to see the complete definition of impl (in order to destroy the std::unique_ptr). Note that we have also explicitly defaulted the move constructor and assignment operator on lines 42–43 so that foo can be moved. To make foo copyable, we must also implement the copy constructor and assignment operator.

Note: std::make_unique was introduced in C++14. For C++11, you can roll your own implementation.

 

Brief example

// foo.h - header file
#include <memory>
class foo
{
    public:
        foo();
        ~foo();
        foo(foo&&);
        foo& operator=(foo&&);
    private:
        class impl;
        std::unique_ptr 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()}
{
    pimpl->do_internal_work();
}
foo::~foo() = default;
foo::foo(foo&&) = default;
foo& foo::operator=(foo&&) = default;

 

TAGS
RELATED POSTS
VLAD VESA
Timisoara, RO

Hi my name is Vlad and this is my Journey! I use this awesome blog theme to tell people my story. Through all the places and things I see around the world, there isn't a better way to share my experience! Follow my daily updates and discover with me the essence of traveling!

Latest tweets
  • Trying out @theTunnelBear so I can browse privately from my ISP https://t.co/nTKZxipi9d https://t.co/nGJHmMue9O

    Tweeted on 10:41 PM Oct 27

  • just bought a @lenovo yoga 720 beautiful machine! good build quality and unexpected package content! https://t.co/nNHj7WCK6A

    Tweeted on 10:13 PM Oct 27