¿Hay alguna razón para que la clase de implementación utilizada en el idioma pimpl tenga miembros privados? La única razón por la que realmente puedo pensar es para protegerse de usted mismo, es decir, los miembros privados sirven para imponer algún tipo de contrato entre la clase y el usuario, y en este caso la clase y el usuario están íntimamente relacionados, por lo que parece innecesario¿Miembros privados en la clase pimpl?
Respuesta
I Creo que la gente está confundiendo el idioma Pimpl con el Adaptador/Puente/Estrategia patrones. Los modismos son específicos de un idioma. Los patrones pueden aplicarse a muchos idiomas.
El modismo Pimpl se diseñó para abordar el siguiente problema en C++: Los miembros privados de una clase son visibles en la declaración de clase, lo que agrega innecesarias #include dependencias al usuario de la clase. Esta expresión también se conoce como compilador de firewall.
Si la implementación se escribe directamente en el archivo * .cpp correspondiente de la clase externa y no se puede acceder fuera del módulo, entonces Creo que está perfectamente bien simplemente usar una estructura para la clase Pimpl. Para más volver a reforzar la idea de que las implementaciones no están destinados a ser directamente reutilizado, yo los defino como una estructura interna privada:
// foo.h
class Foo : boost::noncopyable
{
public:
...
private:
struct Impl;
boost::scoped_ptr<Impl> impl_;
};
// foo.cpp
struct Foo::Impl
{
// Impl method and member definitions
};
// Foo method definitions
Tan pronto como hay un archivo de cabecera para la clase de implementación, creo que ya no están hablando del idioma Pimpl. Estamos hablando de Adaptador, Puente, Estrategia, clases de interfaz, etc. ...
Solo mis 2 centavos.
¿Por qué no debería tener miembros privados? El hecho de que esté definiendo una interfaz como PIMPL no significa que en ningún otro momento quiera usar la clase.
Todavía es una clase. Los datos probablemente deberían ser privados o estar protegidos. Operaciones sobre datos que nunca serán accesibles al público, privado o protegido. Operaciones que quizás desee exponer, proteger o publicitar.
Mi razón principal para no querer miembros privados es pura pereza: no quiero ofrecer acceso. Me doy cuenta de que también puede haber miembros que deberían ser privados y que no requieren usuarios también. – Anne
Es realmente una clase "privada", accesible solo dentro de un archivo cpp. Una estructura C-style está bien para el propósito en la mayoría de los casos. –
Nemanja: Esto supone que el exterior y el interior se escriben al mismo tiempo. He agregado pimpl después del hecho a las implementaciones existentes. –
En teoría, una clase de pimpl es todavía una clase como cualquier otra. Que es una implementación concreta de una interfaz no significa que otro código no sea un cliente de la misma clase de pimpl.
Dicho esto, en la práctica he encontrado que las clases pimpl tienden a ser mucho más parecidas a las estructuras con algunas funciones miembro en lugar de objetos completos, y tienen menos necesidad de separar la interfaz de la implementación.
Depende de su implementación de pImpl, específicamente donde aplica la invariante de clase, pero en general no veo la necesidad de que la parte impl tenga miembros protegidos/privados. De hecho, generalmente lo declaro como una estructura.
(no he entendido bien la pregunta, así que voy a cambiar mi respuesta.)
La clase de aplicación, que está apuntado por la clase con el pimpl, debe haber una clase regular, con apenas tanto razón para ocultar detalles privados como cualquier otro. De hecho, a menudo es una clase preexistente, con la capa pimpl agregada más tarde para romper dependencias y quizás simplificar un poco la interfaz.
La clase preexistente es la parte "externa", no la parte "impl". –
Lo he visto en ambos sentidos. A veces pimpl es una forma de poner una interfaz consistente sobre las implementaciones que están sujetas a cambios. Otras veces, pimpl es una manera de ocultar completamente la implementación, rompiendo las dependencias en tiempo de compilación. De hecho, ambos pueden ser objetivos. –
La única razón por la que realmente ocurre es protegerse a sí mismo de
por lo que "privado" y "protegido" hay en el primer lugar. Por supuesto, debe usarlos en su implementación; el único momento en que no lo haría es si la implementación no tiene ningún comportamiento (en cuyo caso no es realmente una implementación).
Porque private
significa una mejor encapsulación de datos.
Parece una tontería, lo sé, pero tenemos una manera de definir las interfaces en el trabajo que es muy simple:
class Interface;
class Concrete { public: .... private: Interface* m_interface; }
class ConcreteFoo: public Interface {};
La principal ventaja: se puede cambiar por otra ConcreteBar
en cualquier momento. Es, de hecho, una combinación de Pimpl
y Strategy
patrón, y el constructor de Concrete
llamará a Factory
que será responsable de servir al objeto efectivo.
Si no puede pensar en una segunda forma de implementar el corazón, simplemente conéctelo en una clase.De esta forma, si luego tiene que refactorizar, solo tendrá que componer un resumen Interface
con el mismo conjunto de métodos, cambiar algunos punteros (y el constructor) y estará bien;)
- 1. ¿Cómo ocultar miembros privados de una clase?
- 2. Accediendo a miembros privados
- 3. Heredando miembros privados en C++
- 4. C++ miembros privados de la clase base abstracta
- 5. Miembros privados y protegidos: C++
- 6. Esconder datos privados miembros? (C++)
- 7. Serializar datos de miembros privados
- 8. acceso a los datos privados de los miembros de la clase externa en la clase interna
- 9. amigo con clase pero no puede acceder a miembros privados
- 10. ¿por qué la clase derivada hereda los miembros privados de la clase base?
- 11. Declaración de variables de miembros privados
- 12. Clase anidada 'acceso a la clase adjunta' miembros de datos privados
- 13. En clases anidadas de Java, ¿puede la clase adjunta acceder a miembros privados de clases internas?
- 14. Javadoc con Gradle: mostrar también miembros privados
- 15. Acceso a los miembros privados de PowerShell
- 16. Acceso miembros privados de plugin de jQuery
- 17. ¿Cómo uso los ayudantes de clase para acceder a miembros privados estrictos de una clase?
- 18. ¿Cómo hacer que una clase pueda acceder solo a ciertos miembros privados de otra clase?
- 19. ¿Variables/métodos privados en la clase anónima?
- 20. Cómo excluir miembros privados de la regla de StyleCop SA1600
- 21. ¿La herencia protegida permite que la clase derivada tenga acceso a los miembros privados de su clase base?
- 22. ¿Por qué definir miembros privados debajo de miembros públicos en C++?
- 23. ¿Los miembros privados son realmente más "seguros" en Java?
- 24. CoffeeScript Miembros de la Clase
- 25. ¿Cómo puede Spring/Hibernate acceder a miembros privados?
- 26. ¿Pudo C++ no haber obviado el modismo pimpl?
- 27. ¿Miembros genéricos de la clase en C#?
- 28. Métodos que utilizan miembros privados o accesadores públicos
- 29. ¿Cómo puedo utilizar PrivateObject para acceder a miembros privados de mi clase y su principal?
- 30. PIMPL y la asignación de la pila
Suponiendo una implementación agrupada para cadenas de sólo lectura, la clase de implementación puede tener un recuento de referencias para saber cuándo liberar la memoria, si es necesario. – dirkgently
dirkgently: Me imagino que, para tener un conteo simple para todas las referencias a una cadena, ese conteo tendría que ser almacenado centralmente, dentro de la cadena y no en el contenedor. ¿Que me estoy perdiendo aqui? –
@Steven Sudit: porque violaría el diseño; el recuento de referencias no es estrictamente parte de la estructura de datos necesaria para representar la cadena. – dirkgently