Thursday, October 6, 2016

C++ PIMPL idiom

One of the biggest problem with C++ is that it does not have a convenient way to define an interface. Java has simplified this by providing a syntax for defining interface class.

A normal way of writing a header in C++ exposes all its internal details of private/public variables, private functions along with the actual exported public functions. This is not ideal when we want to build a library with exported interfaces.

Consider the following example:

class Car {
public:
   Car(const std::string &make, const std::string &name);
   virtual ~Car() {}

   const string& getMake() const { return _make; }
   const string& getName() const { return _name; }

private:
   std::string _make;
   std::string _name;
};

Any changes in implementation of this class which requires additional private variables will result in a change in this declaration. So even though there is no change in public interface to the external users, the code using this class will get recompiled if this declaration changes.

One technique to separate out interface is to use abstract classes defining only the public interfaces.

class IVehicle {
public:
   virtual ~IVehicle() = 0;

   virtual const string& getMake() const = 0;
   virtual const string& getName() const = 0;
};

This interface class is implemented by 'Car' class.
So now we need a function to create an instance of 'Car'. Since we want to hide the declaration of 'Car', usual approach is to provide a static create function.

static IVehicle * createCar() {
   IVehicle *car = new Car();
   return car;
}

Create function could return a shared_pointer so that the user is saved from keeping track of the instance and freeing it when done.
This approach is generally used in Windows programming.

But here we are going to discuss another method to separate interface from implementation. It is called PIMPL(private implementation) idiom (also called Cheshire Cat).

class Car {
public:
   Car(const std::string &make, const std::string &name);
   virtual ~Car();

   const string& getMake() const;
   const string& getName() const;

private:
   class CarImpl;
   CarImpl *_pCarImpl;
};

All the implementation details are hidden in the private implementation 'CarImpl'.  Implementation of 'Car' is just some boiler plate code to redirect all calls to 'CarImpl'. We can use unique_pointer for the private implementation instance to prevent memory leaks.

With this method, we have successfully separated the interface from implementation and achieved implementation hiding. We also do not need any create function, as the users can instantiate 'Car' class.

So far so good, but what if we want to create a class that inherits from class 'Car'? How do we create a private implementation of the derived class?

class Sedan : public Car {
public:
   Sedan(const std::string &make, const std::string &name);
   virtual ~Sedan();

   const string& getMake() const;
   const string& getName() const;

private:
   class SedanImpl;
   SedanImpl *_pSedanImpl;
};

The new class 'Sedan' is derived from 'Car'. Now how about the pimpl class 'SedanImpl'.

class SedanImpl : public CarImpl {
public:
   ...
};

The private implementation is derived from the base class pimpl i.e. 'CarImpl'.

If you notice, now we have two separate instances of pimpl classes instantiated when 'Sedan' is instantiated - '_pCarImpl' in base class and '_pSedanImpl' in derived class. How can we avoid this?

We can solve this by passing the pointer to instance of 'SedanImpl' to base class in constructor.

class Car {
public:
   Car(const std::string &make, const std::string &name);
   virtual ~Car();

   const string& getMake() const;
   const string& getName() const;

protected:
   Car(const std::string &make, const std::string &name, CarImpl *pCarImpl);
   CarImpl *getImpl() { return _pCarImpl; }

private:
   class CarImpl;
   CarImpl *_pCarImpl;
};

A protected constructor is added in 'Car' which takes an additional pointer to 'CarImpl' as parameter. Also we added a function to return the pimpl instance.
And now in 'Sedan' constructor we can invoke this base class constructor.

class Sedan : public Car {
public:
   Sedan(const std::string &make, const std::string &name)
                  : Car(make, name, new SedanImpl()) {}
   virtual ~Sedan();

   const string& getMake() const;
   const string& getName() const;
};

So now we don't need a private instance of 'SedanImpl' here. To get the pimpl instance in 'Sedan' use the base class function 'getImpl' and static_cast it to 'SedanImpl'.

Now the obvious question arises, what is the benefit of using PIMPL over abstract interface class?
Here is an excellent explanation:
http://programmers.stackexchange.com/questions/213259/whats-is-the-point-of-pimpl-pattern-while-we-can-use-interface-for-the-same-pur