En programación informática , un puntero opaco es un caso especial de un tipo de datos opaco , un tipo de datos declarado como puntero a un registro o estructura de datos de algún tipo no especificado.
Los punteros opacos están presentes en varios lenguajes de programación, incluidos Ada , C , C ++ , D y Modula-2 .
Si el lenguaje está fuertemente tipado , los programas y procedimientos que no tienen otra información sobre un puntero opaco tipo T aún pueden declarar variables , matrices y campos de registro de tipo T , asignar valores de ese tipo y comparar esos valores para la igualdad. Sin embargo, no podrán quitar la referencia a dicho puntero y solo podrán cambiar el contenido del objeto llamando a algún procedimiento que tenga la información que falta.
Los punteros opacos son una forma de ocultar los detalles de implementación de una interfaz de los clientes normales, de modo que la implementación pueda cambiarse sin la necesidad de volver a compilar los módulos que la utilizan. Esto también beneficia al programador, ya que se puede crear una interfaz simple y la mayoría de los detalles se pueden ocultar en otro archivo. [1] Esto es importante para proporcionar compatibilidad de código binario a través de diferentes versiones de una biblioteca compartida , por ejemplo.
Esta técnica se describe en Patrones de diseño como patrón Puente . A veces se lo conoce como " clases de control ", [2] el " idioma Pimpl " (para "puntero al idioma de implementación"), [3] " idioma del cortafuegos del compilador ", [4] " d-pointer" o " Cheshire Cat ", especialmente entre la comunidad de C ++. [2]
Ejemplos de
Ada
paquete Library_Interface es el tipo de identificador es privado limitado ; - Operaciones ... tipo privado Hidden_Implementation ; - Definido en el tipo de cuerpo del paquete Handle es access Hidden_Implementation ; end Library_Interface ;
El tipo Handle
es un puntero opaco a la implementación real, que no está definida en la especificación. Tenga en cuenta que el tipo no solo es privado (para prohibir que los clientes accedan al tipo directamente, y solo a través de las operaciones), sino también limitado (para evitar la copia de la estructura de datos y así evitar referencias colgantes).
El cuerpo del paquete Library_Interface es type Hidden_Implementation es record ... - La implementación real puede ser cualquier cosa final record ; - Definición de las operaciones ...end Library_Interface ;
Estos tipos a veces se denominan " tipos Taft " —nombrados en honor a Tucker Taft , el diseñador principal de Ada 95— porque se introdujeron en la llamada Enmienda Taft a Ada 83. [5]
C
/ * obj.h * /struct obj ;/ * * El compilador considera struct obj como un tipo incompleto. Los tipos incompletos * se pueden utilizar en declaraciones. * /size_t obj_size ( vacío );void obj_setid ( struct obj * , int );int obj_getid ( struct obj * );
/ * obj.c * /#include "obj.h"struct obj { int id ; };/ * * La persona que llama se encargará de la asignación. * Proporcione solo la información requerida * /size_t obj_size ( void ) { return sizeof ( estructura obj ); }void obj_setid ( struct obj * o , int i ) { o -> id = i ; }int obj_getid ( struct obj * o ) { return o -> id ; }
Este ejemplo demuestra una forma de lograr el aspecto de ocultación de información ( encapsulación ) de la programación orientada a objetos utilizando el lenguaje C. Si alguien quisiera cambiar la definición de struct obj
, sería innecesario recompilar cualquier otro módulo en el programa que use el obj.h
archivo de encabezado a menos que también se cambie la API . Tenga en cuenta que puede ser deseable que las funciones verifiquen que el puntero pasado no lo sea NULL
, pero dichas verificaciones se han omitido anteriormente por brevedad.
C ++
/ * PublicClass.h * /#include clase PublicClass { public : PublicClass (); // Constructor PublicClass ( const PublicClass & ); // Copiar constructor PublicClass ( PublicClass && ); // Mover el constructor PublicClass & operator = ( const PublicClass & ); // Copiar el operador de asignación PublicClass & operator = ( PublicClass && ); // Mover el operador de asignación ~ PublicClass (); // Destructor // Otras operaciones ... privado : struct CheshireCat ; // No definido aquí std :: unique_ptr < CheshireCat > d_ptr_ ; // Puntero opaco };
/ * PublicClass.cpp * /#include "PublicClass.h"struct PublicClass :: CheshireCat { int a ; int b ; };PublicClass :: PublicClass () : d_ptr_ ( std :: make_unique < CheshireCat > ()) { // No hacer nada. }PublicClass :: PublicClass ( const PublicClass y otros ) : d_ptr_ ( std :: make_unique < CheshireCat > ( * other . D_ptr_ )) { // No hacer nada. }PublicClass :: PublicClass ( PublicClass && otro ) = predeterminado ;PublicClass y PublicClass :: operator = ( const PublicClass y otro ) { * d_ptr_ = * otro . d_ptr_ ; devolver * esto ; }PublicClass & PublicClass :: operator = ( PublicClass && ) = predeterminado ;PublicClass :: ~ PublicClass () = predeterminado ;
El patrón de puntero d es una de las implementaciones del puntero opaco . Se usa comúnmente en las clases de C ++ debido a sus ventajas (que se indican a continuación). Un d-pointer es un miembro de datos privados de la clase que apunta a una instancia de una estructura. Este método permite que las declaraciones de clase omitan miembros de datos privados, excepto el propio d-pointer. [6] Como resultado,
- más de la implementación de la clase está oculta
- agregar nuevos miembros de datos a la estructura privada no afecta la compatibilidad binaria
- el archivo de encabezado que contiene la declaración de clase solo necesita incluir los archivos necesarios para la interfaz de clase, en lugar de para su implementación.
Un beneficio adicional es que las compilaciones son más rápidas porque el archivo de encabezado cambia con menos frecuencia. Tenga en cuenta que la posible desventaja del patrón d-pointer es el acceso indirecto a los miembros a través de un puntero (por ejemplo, un puntero a un objeto en el almacenamiento dinámico), que a veces es más lento que el acceso a un miembro simple que no es un puntero. El d-pointer se usa mucho en las bibliotecas Qt [7] y KDE .
Ver también
Referencias
- ^ Chris McKillop. "Herramientas de programación - Punteros opacos" . Sistemas de software QNX . Consultado el 16 de enero de 2019 .
- ^ a b Bruce Eckel (2000). "Capítulo 5: Ocultar la implementación" . Pensando en C ++, Volumen 1: Introducción a C ++ estándar (2ª ed.). Prentice Hall. ISBN 0-13-979809-9.
- ^ Vladimir Batov (25 de enero de 2008). "Haciendo Pimpl fácil" . Diario del Dr. Dobb . Consultado el 7 de mayo de 2008 .
- ^ Herb Sutter. The Joy of Pimpls (o más sobre el lenguaje compilador-firewall)
- ^ Robert A. Duff (29 de julio de 2002). "Re: ¿Cuál es su nombre de nuevo?" . Grupo de noticias : comp.lang.ada . Consultado el 11 de octubre de 2007 .
- ^ Usando un d-Pointer - Por qué y cómo KDE implementa punteros opacos
- ^ "D-Pointer" . Qt wiki . Consultado el 23 de diciembre de 2016 .
enlaces externos
- El idioma de Pimpl
- Cortafuegos de compilación
- El lenguaje rápido de la espinilla
- Punteros D - KDE TechBase
- Cuando "XOR el puntero con un número aleatorio" [1] [2] , el resultado es un puntero "realmente opaco" [3] .
- Haciendo que Pimpl sea fácil , Vladimir Batov