Pregunta

En la sección sobre "buena encapsulación" en el código completo, se recomienda ocultar detalles de implementación privada. Se da un ejemplo en C ++. La idea es básicamente separar completamente la interfaz de la implementación, incluso en el nivel de clase.

class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};

¿Es esto realmente un buen uso del tiempo? Esto no solo parece ineficiente (¿qué tipo de sanciones de rendimiento darían esto?), Sino que todo el lema de código completo ("administrar complejidad") parece haberse revertido, ¿no? agregar ¿complejidad?

¿Fue útil?

Solución

Otra ventaja del lenguaje de Pimpl puede ser mantener el Abi. Ver El idioma Pimpl en la práctica.

los Talla de la clase permanece constante. Esto significa que puede cambiar la implementación interna, mientras mantiene intacta la interfaz.

Si la implementación se distribuye en forma compilada (lib, dll, así, etc.), entonces, en algunas condiciones, puede reemplazar la biblioteca sin tener que recompilar el código que usa la clase. Por lo tanto, desacopla el código como un módulo completamente independiente, siempre que la interfaz pública no cambie.

Como otros han declarado, también reduce el tiempo de compilación, lo que puede ser una razón suficiente en algunos casos.

Otros consejos

Bueno, aumenta la encapsulación ya que su archivo de encabezado ahora contiene solo miembros públicos y un solo puntero a una implementación privada.

También (¿ligeramente?) Reduce el rendimiento debido al nivel adicional de indirección.

El "Reduce el tiempo de compilación" es el tema clave aquí.

Si usted (su empresa) es los únicos usuarios de la clase, entonces no creo que tenga ninguna razón para usar este idioma. Obtiene un rendimiento más bajo y debe tener reconstrucciones diarias (o periódicas) de su código fuente de todos modos (lo que debe tener en cuenta las dependencias entre las clases).

Esto significa que el tiempo de compilación debe ser en gran medida irrelevante si usted es el único consumidor de la clase.

Si está distribuyendo la biblioteca, la historia es completamente diferente. Los cambios en los encabezados significan que cualquier cliente que tenga necesitará reconstruir sus aplicaciones para usar su nueva versión, incluso si lo que hizo fue cambiar las partes privadas de la clase. Usar el idioma Pimpl aquí significaría que el cambio es invisible para los usuarios de su biblioteca dinámica.

Un nivel adicional de indirección a través del puntero puede causar fallas de caché adicionales y ralentizar su programa. AFAIK, este idioma (PIMPL) se sugiere con mayor frecuencia para reducir el tiempo de compilación. Di que tienes un employee.h encabezado que tiene todos los campos en la clase, en lugar de solo un puntero. Ahora, cada vez que cambia los detalles del empleado (por ejemplo, agregar o eliminar campo), cada archivo, incluido employee.h tiene que ser recompilado. Si todo lo que tiene es un solo puntero a una clase de implementación definida en employee.cpp, entonces solo employee.cpp tiene que ser recompilado cuando cambias EmployeeImplementation.

Ahora, ¿el tiempo de compilación reducido vale la pena el costo adicional? Solo tú puedes decidir eso.

Creo que la principal ventaja (o al menos en ellas) del idioma Pimpl no está ahorrando el tiempo de compilación, sino que permite bajo acoplamiento, es decir, las dependencias de ruptura, entre componentes.

Supongamos que proporciona una biblioteca de infraestructura que usan muchos otros componentes. Luego, como indicó @ZVRBA, cada vez que cambia sus detalles de implementación privada, todos sus clientes deben recompilar. No podría ser un gran problema, pero en proyectos grandes y complejos, una integración entre los componentes puede ser una tarea compleja. Con PIMPL, si su biblioteca es dinámica (dll, .sO), entonces sus clientes no requieren ninguna acción.

Este idioma se usa para abstraer sobre encabezados pobres y no mucho más. Solo úselo si los tipos necesarios para definir la clase implican incluir encabezados que filtran macros, tardan mucho tiempo en compilar, etc. Aparte de eso, generalmente no se considera lo correcto. Dado que su implementación requiere asignación dinámica y semántica de referencia de todos modos, también puede convertirlo en una interfaz y ofrecer una CreateForMyPlatform() Método que tiene una definición en un archivo CPP. Al menos puedes usar consejos inteligentes para ese escenario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top