Go back to Richel Bilderbeek's homepage.
Go back to Richel Bilderbeek's C++ page.
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 methods of the Pimpl
class will (often) call the methods of the
implementation class with the same name.
The advantages of using the Pimpl idiom are:
- Shorten build times [1]
- Remove visibility of private methods [1]
- Improved error handling and safety [1]
- Personally, I also use it to make a non-copyable class (for example, one with constant member variables) copyable (instead of defining operator=)
The disadvantage of using the Pimpl idiom is the cost of
an extra level of indirection, so Pimpl judiciously [1].
Example
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
//---------------------------------------------------------------------------
// UnitLizard.h
//---------------------------------------------------------------------------
#ifndef UnitLizardH
#define UnitLizardH
//---------------------------------------------------------------------------
#include <boost/shared_ptr.hpp>
//---------------------------------------------------------------------------
enum Gender { male, female };
struct Lizard
{
Lizard(const Gender gender);
const Gender GetGender() const;
private:
struct LizardImpl;
boost::shared_ptr<LizardImpl> mPimpl;
};
#endif
|
lizard.cpp
//---------------------------------------------------------------------------
// UnitLizard.cpp
//---------------------------------------------------------------------------
#include "UnitLizard.h"
//---------------------------------------------------------------------------
struct Lizard::LizardImpl
{
LizardImpl(const Gender gender);
const Gender mGender;
};
//---------------------------------------------------------------------------
Lizard::Lizard(const Gender gender)
: mPimpl(boost::shared_ptr<LizardImpl>(new LizardImpl(gender) ) )
{
}
//---------------------------------------------------------------------------
const Gender Lizard::GetGender() const
{
return mPimpl->mGender;
}
//---------------------------------------------------------------------------
// The actual Lizard implementation
//---------------------------------------------------------------------------
Lizard::LizardImpl::LizardImpl(const Gender gender) : mGender(gender)
{
}
//---------------------------------------------------------------------------
|
- Herb Sutter, Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Item 43: 'Pimpl judiciously'.
Go back to Richel Bilderbeek's C++ page.
Go back to Richel Bilderbeek's homepage.

This page has been created by the tool CodeToHtml