mantener partes privadas fuera de los encabezados de c ++: clase base virtual pura vs pimpl

Recientemente cambié de Java y Ruby a C ++, y para mi sorpresa, tengo que recompilar archivos que usan la interfaz pública cuando cambio la firma del método de un método privado, porque también las partes privadas están en el archivo .h.

Rápidamente se me ocurrió una solución que es, supongo, típica de un programador de Java: interfaces (= clases base virtuales puras). Por ejemplo:

BananaTree.h:

class Banana;

class BananaTree
{
public:
  virtual Banana* getBanana(std::string const& name) = 0;

  static BananaTree* create(std::string const& name);
};

BananaTree.cpp:

class BananaTreeImpl : public BananaTree
{
private:
  string name;

  Banana* findBanana(string const& name)
  {
    return //obtain banana, somehow;
  }

public:
  BananaTreeImpl(string name) 
    : name(name)
  {}

  virtual Banana* getBanana(string const& name)
  {
    return findBanana(name);
  }
};

BananaTree* BananaTree::create(string const& name)
{
  return new BananaTreeImpl(name);
}

La única molestia aquí es que no puedo usarnew, y en su lugar debe llamarBananaTree::create(). No creo que eso sea realmente un problema, especialmente porque espero usar muchas fábricas de todos modos.

Ahora, los sabios de la fama de C ++, sin embargo, encontraron otra solución, lamodismo de ejemplo. Con eso, si lo entiendo correctamente, mi código se vería así:

BananaTree.h:

class BananaTree
{
public:
  Banana* addStep(std::string const& name);

private:
  struct Impl;
  shared_ptr<Impl> pimpl_;
};

BananaTree.cpp:

struct BananaTree::Impl
{
  string name;

  Banana* findBanana(string const& name)
  {
    return //obtain banana, somehow;
  }

  Banana* getBanana(string const& name)
  {
    return findBanana(name);
  }

  Impl(string const& name) : name(name) {}
}

BananaTree::BananaTree(string const& name)
  : pimpl_(shared_ptr<Impl>(new Impl(name)))
{}

Banana* BananaTree::getBanana(string const& name)
{
  return pimpl_->getBanana(name);
}

Esto significaría que tengo que implementar un método de reenvío estilo decorador para cada método público deBananaTree, en este casogetBanana. Esto suena como un nivel adicional de complejidad y esfuerzo de mantenimiento que prefiero no requerir.

Entonces, ahora para la pregunta: ¿Qué tiene de malo el enfoque de clase virtual pura? ¿Por qué el enfoque pImpl está mucho mejor documentado? ¿Yo me perdí algo?

Respuestas a la pregunta(2)

Su respuesta a la pregunta