Pimpl Idiom

Normally a class is written like

// Foo.h
#include <string>
#include <vector>
 
class Foo
{
public:
	void greet();
private:
	std::string name;
	std::vector<int> data;
};

But now, every .cpp file that includes Foo.h must now also include <string> and <vector>.

If you later change Foo’s private members (say replace std::vector with std::deque), all those .cpp files need recompiling, even though those files only use Foo’s public API.

This is the problem Pimpl idiom seeks to fix.

The idea:

  • Keep the class interface (header) stable and minimal.
  • Move all data and private functions inside a hidden “implementation” struct that lives in the .cpp file.
  • The main class holds only a pointer (pImpl) to that struct.
// Foo.h
class Foo
{
public:
	Foo();
	~Foo();
	void greet();
private:
	struct Impl;  // Forward declaration only
	Impl* pImpl;  // Pointer to implementation
};
// Foo.cpp
#include "Foo.h"
#include <string>
#include <iostream>
 
struct Foo::Impl
{
	std::string name = "Ethan";
	void greetImpl()
	{
		std::cout << "Hello, " << name << "!" << std::endl;
	}
};
 
Foo::Foo() : pImpl(new Impl) {}
Foo::~Foo() { delete pImpl; }
 
void Foo::greet() { pImpl->greetImpl(); }

Now, anyone including Foo.h doesn’t need to know about <string> or <iostream>. They just see class Foo { … };.

Why Use Pimpl?

Main reasons:

  1. Encapsulation at compile-time

Your private members are truly private, even the compiler outside your .cpp doesn’t know them.

  1. Faster compile times

Changing private data types doesn’t force recompilation of other files.

  1. Binary compatibility (ABI stability)

If you ship a library (say libFoo.so), changing private details doesn’t break programs that link to it.

  1. Cleaner headers

Your .h files include only what’s truly needed for the interface, not implementation headers.

Downsides

  • Slight runtime cost (one extra pointer indirection).
  • More boilerplate (constructors, forwarding functions).
  • Not always worth it for small, local projects, but very valuable in libraries or large codebases.