Entonces, me pregunto si esta técnica se usa realmente en la práctica. ¿Debo usarlo en todas partes o con precaución?
Por supuesto que se usa. Lo uso en mi proyecto, en casi todas las clases.
Razones para usar el idioma PIMPL:
Compatibilidad binaria
Cuando está desarrollando una biblioteca, puede agregar / modificar campos XImpl
sin romper la compatibilidad binaria con su cliente (¡lo que significaría fallas!). Dado que el diseño binario de la X
clase no cambia cuando agrega nuevos campos a la Ximpl
clase, es seguro agregar nueva funcionalidad a la biblioteca en actualizaciones de versiones menores.
Por supuesto, también puede agregar nuevos métodos no virtuales públicos / privados para X
/ XImpl
sin romper la compatibilidad binaria, pero eso está a la par con la técnica estándar de encabezado / implementación.
Ocultar datos
Si está desarrollando una biblioteca, especialmente una propiedad, puede ser conveniente no revelar qué otras bibliotecas / técnicas de implementación se usaron para implementar la interfaz pública de su biblioteca. Ya sea por problemas de propiedad intelectual o porque cree que los usuarios podrían verse tentados a asumir suposiciones peligrosas sobre la implementación o simplemente romper la encapsulación mediante el uso de trucos de lanzamiento terribles. PIMPL resuelve / mitiga eso.
Tiempo de compilación
El tiempo de compilación disminuye, ya que solo el archivo de origen (implementación) X
debe reconstruirse cuando agrega / elimina campos y / o métodos a la XImpl
clase (que se asigna para agregar campos / métodos privados en la técnica estándar). En la práctica, es una operación común.
Con la técnica estándar de encabezado / implementación (sin PIMPL), cuando agrega un nuevo campo a X
, cada cliente que asigna X
(ya sea en la pila o en el montón) debe volver a compilarse, ya que debe ajustar el tamaño de la asignación. Bueno, todos los clientes que nunca asignan X también deben volver a compilarse, pero son solo gastos generales (el código resultante en el lado del cliente será el mismo).
Además, con la separación estándar de encabezado / implementación, se XClient1.cpp
debe volver a compilar incluso cuando X::foo()
se agregó X
y X.h
cambió un método privado , ¡aunque XClient1.cpp
no es posible llamar a este método por razones de encapsulación! Al igual que arriba, es pura sobrecarga y está relacionado con la forma en que funcionan los sistemas de compilación C ++ de la vida real.
Por supuesto, la recompilación no es necesaria cuando solo modifica la implementación de los métodos (porque no toca el encabezado), pero eso está a la par con la técnica estándar de encabezado / implementación.
¿Se recomienda utilizar esta técnica en sistemas integrados (donde el rendimiento es muy importante)?
Eso depende de cuán poderoso sea tu objetivo. Sin embargo, la única respuesta a esta pregunta es: medir y evaluar lo que gana y pierde. Además, tenga en cuenta que si no está publicando una biblioteca destinada a ser utilizada en sistemas integrados por sus clientes, ¡solo se aplica la ventaja de tiempo de compilación!
struct XImpl : public X
. Eso me parece más natural. ¿Hay algún otro problema que me haya perdido?