Veo un montón de código fuente que usa la expresión de PImpl en C ++. Supongo que su propósito es ocultar los datos / tipo / implementación privados, para que pueda eliminar la dependencia y luego reducir el tiempo de compilación y el problema de inclusión del encabezado.
Pero las clases interface / pure-abstract en C ++ también tienen esta capacidad, también se pueden usar para ocultar datos / tipo / implementación. Y para permitir que la persona que llama solo vea la interfaz al crear un objeto, podemos declarar un método de fábrica en el encabezado de la interfaz.
La comparación es:
coste :
El costo de la interfaz es más bajo, ya que ni siquiera necesita repetir la implementación de la función de contenedor público
void Bar::doWork() { return m_impl->doWork(); }
, solo necesita definir la firma en la interfaz.Bien entendido :
La tecnología de interfaz es mejor entendida por todos los desarrolladores de C ++.
Rendimiento :
El rendimiento de la interfaz no es peor que el idioma de PImpl, tanto un acceso a memoria adicional. Supongo que el rendimiento es el mismo.
El siguiente es el pseudocódigo para ilustrar mi pregunta:
// Forward declaration can help you avoid include BarImpl header, and those included in BarImpl header.
class BarImpl;
class Bar
{
public:
// public functions
void doWork();
private:
// You don't need to compile Bar.cpp after changing the implementation in BarImpl.cpp
BarImpl* m_impl;
};
El mismo propósito se puede implementar usando la interfaz:
// Bar.h
class IBar
{
public:
virtual ~IBar(){}
// public functions
virtual void doWork() = 0;
};
// to only expose the interface instead of class name to caller
IBar* createObject();
Entonces, ¿cuál es el punto de PImpl?
fuente
Impl
la clase no rompa elABI
, además de añadir la función pública en la interfaz se romperáABI
.unordered_set
), sin PImpl, necesito#include <unordered_set>
enMyClass.h
. Con PImpl, solo necesito incluirlo en el.cpp
archivo, no en el.h
archivo, y por lo tanto, todo lo demás que lo incluye ...Solo quiero abordar su punto de rendimiento. Si usa una interfaz, necesariamente ha creado funciones virtuales que NO serán alineadas por el optimizador del compilador. Las funciones PIMPL pueden (y probablemente lo harán, porque son muy cortas) estar en línea (quizás más de una vez si la función IMPL también es pequeña). Una llamada de función virtual no se puede optimizar a menos que use optimizaciones de análisis de programa completas que tardan mucho tiempo en realizarse.
Si su clase PIMPL no se usa de manera crítica para el rendimiento, entonces este punto no importa mucho, pero su suposición de que el rendimiento es el mismo solo se aplica en algunas situaciones, no en todas.
fuente
Esta página responde a su pregunta. Mucha gente está de acuerdo con tu afirmación. Usar Pimpl tiene las siguientes ventajas sobre los campos / miembros privados.
El idioma de Pimpl es una optimización en tiempo de compilación, una técnica de ruptura de dependencia. Corta grandes archivos de encabezado. Reduce su encabezado a solo la interfaz pública. La longitud del encabezado es importante en C ++ cuando piensa en cómo funciona. #include efectivamente concatena el archivo de encabezado con el archivo de origen, así que tenga en cuenta que las unidades C ++ preprocesadas pueden ser muy grandes. Usar Pimpl puede mejorar los tiempos de compilación.
Existen otras mejores técnicas para romper la dependencia, que implican mejorar su diseño. ¿Qué representan los métodos privados? ¿Cuál es la responsabilidad única? ¿Deberían ser otra clase?
fuente