¿Por qué debería usarse el modismo "PIMPL"? [duplicar]
Antecedentes:
El modismo PIMPL (puntero a IMPLementation) es una técnica para ocultar implementaciones en la que una clase pública envuelve una estructura o clase que no se puede ver fuera de la biblioteca de la que forma parte la clase pública.
Esto oculta detalles y datos de implementación interna al usuario de la biblioteca.
Al implementar este modismo, ¿por qué colocaría los métodos públicos en la clase pimpl y no en la clase pública, ya que las implementaciones de los métodos de las clases públicas se compilarían en la biblioteca y el usuario solo tendría el archivo de encabezado?
Para ilustrar, este código coloca la Purr()
implementación en la clase impl y también la envuelve.
¿Por qué no implementar Purr directamente en la clase pública?
// header file:
class Cat {
private:
class CatImpl; // Not defined here
CatImpl *cat_; // Handle
public:
Cat(); // Constructor
~Cat(); // Destructor
// Other operations...
Purr();
};
// CPP file:
#include "cat.h"
class Cat::CatImpl {
Purr();
... // The actual implementation can be anything
};
Cat::Cat() {
cat_ = new CatImpl;
}
Cat::~Cat() {
delete cat_;
}
Cat::Purr(){ cat_->Purr(); }
CatImpl::Purr(){
printf("purrrrrr");
}
Creo que la mayoría de la gente se refiere a esto como el modismo Handle Body . Consulte el libro de James Coplien Estilos y modismos de programación avanzados en C++ . También se le conoce como el Gato de Cheshire por el carácter de Lewis Carroll que se desvanece hasta que sólo queda la sonrisa.
El código de ejemplo debe distribuirse en dos conjuntos de archivos fuente. Entonces sólo Cat.h es el archivo que se envía con el producto.
CatImpl.h está incluido en Cat.cpp y CatImpl.cpp contiene la implementación de CatImpl::Purr() . Esto no será visible para el público que utilice su producto.
Básicamente, la idea es ocultar la mayor parte posible de la implementación a miradas indiscretas.
Esto es más útil cuando tiene un producto comercial que se envía como una serie de bibliotecas a las que se accede a través de una API con la que se compila y vincula el código del cliente.
Hicimos esto con la reescritura del producto Orbix 3.3 de IONA en 2000.
Como mencionaron otros, el uso de su técnica desacopla completamente la implementación de la interfaz del objeto. Entonces no tendrás que volver a compilar todo lo que usa Cat si solo quieres cambiar la implementación de Purr() .
Esta técnica se utiliza en una metodología llamada diseño por contrato .
- Porque desea
Purr()
poder utilizar miembros privados deCatImpl
.Cat::Purr()
no se le permitiría dicho acceso sin unafriend
declaración. - Porque entonces no se mezclan responsabilidades: una clase implementa, una clase avanza.