(C++) Pimpl

July 25, 2018 · View on GitHub

Pimpl is an abbreviation of 'pointer to implementation'.

The idea of the Pimpl idiom is to give a class (for example 'Lizard') an opaque (smart) pointer to the actual implementation (for example 'LizardImpl'). The opaque (smart) pointer enables it to do a forward declaration of the implementation class only, without the compiler needing to know the actual type. This shortens build times [1]. All the public member functions of the Pimpl class will (often) call the member functions of the implementation class with the same name.

The advantages of using the Pimpl idiom are:

The disadvantage of using the Pimpl idiom is the cost of an extra level of indirection, so Pimpl judiciously [1].

Examples

Most lizards remain having the same gender for all their live. Therefore, it is a good idea to make a lizard's gender a const member variable. Problem is, that this makes a lizard class uncopyable. In this example I solve this by making a Lizard contain an opaque pointer to LizardImpl, where a LizardImpl does have a constant gender. Because I want to be able to do a shallow copy on Lizards, I use a boost::shared_ptr. Also note that the code is very similar to a Strategy design pattern.

 

lizard.h

#ifndef CPP_PIMPL_LIZARD_H
#define CPP_PIMPL_LIZARD_H

enum class Gender { male, female };

#include <memory>

class Lizard
{
public:
  Lizard(const Gender gender);
  ~Lizard();
  Gender GetGender() const noexcept;

private:
  struct LizardImpl;
  std::shared_ptr<LizardImpl> mPimpl;
};

#endif // CPP_PIMPL_LIZARD_H

lizard.cpp

#include "CppPimplLizard.h"

struct Lizard::LizardImpl
{
  LizardImpl(const Gender gender);
  const Gender mGender;
};

Lizard::Lizard(const Gender gender)
  : mPimpl(std::make_shared<LizardImpl>(gender))
{

}

Lizard::~Lizard()
{
  //Need destructor definition in implementation file
}

Gender Lizard::GetGender() const noexcept
{
  return mPimpl->mGender;
}

Lizard::LizardImpl::LizardImpl(const Gender gender) : mGender(gender)
{

}

References

  • [1] Herb Sutter, Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Item 43: 'Pimpl judiciously'.