En programación informática , un puntero opaco es un caso especial de un tipo de datos opaco , un tipo de datos declarado como un 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 de tipo T pueden declarar variables , matrices y campos de registro de tipo T , asignar valores de ese tipo y comparar esos valores para determinar si son iguales. Sin embargo, no podrán desreferenciar dicho puntero y solo podrán cambiar el contenido del objeto llamando a algún procedimiento que tenga la información faltante.
Los punteros opacos son una forma de ocultar los detalles de implementación de una interfaz a los clientes comunes, de modo que la implementación se pueda cambiar sin 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 los Patrones de Diseño como el patrón Bridge . A veces se la conoce como " manejar clases ", [2] " idioma Pimpl " (por "idioma de puntero a implementación"), [3] " idioma de firewall del compilador ", [4] " d-pointer" o " Gato de Cheshire ", especialmente entre la comunidad C++. [2]
Ejemplos
Ada
El paquete Library_Interface es
El tipo Handle es privado limitado ;
--Operaciones...
tipo privado Hidden_Implementation ; -- Definido en el cuerpo del paquete
El tipo Handle es access Hidden_Implementation ;
fin Library_Interface ;
El tipo Handlees un puntero opaco a la implementación real, que no está definida en la especificación. Nótese que el tipo no sólo es privado (para impedir que los clientes accedan al tipo directamente, y sólo a través de las operaciones), sino también limitado (para evitar la copia de la estructura de datos, y así prevenir referencias colgantes).
El cuerpo del paquete Library_Interface es
tipo Hidden_Implementation es registro
... -- La implementación real puede ser cualquier cosa
final registro ;
-- Definición de las operaciones...
fin Biblioteca_Interfaz ;
A estos tipos a veces se les llama " tipos Taft " (en honor a Tucker Taft, el diseñador principal de Ada 95) porque se introdujeron en la llamada Enmienda Taft a Ada 83. [5]
do
/*obj.h*/
estructura obj ;
/*
* El compilador considera que struct obj es un tipo incompleto. Los tipos incompletos
* pueden usarse en declaraciones.
*/
tamaño_t obj_size ( vacío );
vacío obj_setid ( estructura obj * , int );
int obj_getid ( estructura obj * );
/*obj.c*/
#incluir "obj.h"
estructura obj { int id ; };
/*
* El llamador se encargará de la asignación.
* Proporcione únicamente la información requerida
*/
tamaño_t obj_size ( void ) { return sizeof ( struct obj ); }
vacío obj_setid ( estructura obj * o , int i ) { o -> id = i ; }
int obj_getid ( estructura obj * o ) { devolver 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, no sería necesario volver a compilar ningún otro módulo en el programa que use el obj.harchivo de encabezado a menos que también se haya cambiado la API . Tenga en cuenta que puede ser conveniente que las funciones verifiquen que el puntero pasado no sea NULL, pero dichas verificaciones se han omitido anteriormente por razones de brevedad.
C++
/* ClasePública.h */
#include <memoria>
clase PublicClass { public : PublicClass (); // Constructor PublicClass ( const PublicClass & ); // Constructor de copia PublicClass ( PublicClass && ); // Constructor de movimiento PublicClass & operador = ( const PublicClass & ); // Operador de asignación de copia PublicClass & operador = ( PublicClass && ); // Operador de asignación de movimiento ~ PublicClass (); // Destructor
// Otras operaciones...
privado :
struct CheshireCat ; // No definido aquí std :: unique_ptr < CheshireCat > d_ptr_ ; // Puntero opaco };
/*ClasePública.cpp */
#include "ClasePública.h"
estructura PublicClass :: CheshireCat { int a ; int b ; };
PublicClass :: PublicClass ()
: d_ptr_ ( std :: make_unique <CheshireCat> ()) { // No hacer nada. }
PublicClass :: PublicClass ( const PublicClass & other ) : d_ptr_ ( std :: make_unique < CheshireCat > ( * other.d_ptr_ ) ) { // No hacer nada . }
PublicClass :: PublicClass ( PublicClass && other ) = predeterminado ;
PublicClass & PublicClass :: operador = ( const PublicClass & other ) { * d_ptr_ = * other.d_ptr_ ; return * this ; }
PublicClass & PublicClass :: operador = ( PublicClass && ) = predeterminado ;
PublicClass ::~ PublicClass () = predeterminado ;
El patrón d-pointer es una de las implementaciones del puntero opaco . Se utiliza comúnmente en clases de C++ debido a sus ventajas (que se indican a continuación). Un d-pointer es un miembro de datos privado 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,
- La mayor parte 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 aquellos 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. Nótese que la posible desventaja del patrón de puntero d es el acceso indirecto a miembros a través de punteros (por ejemplo, punteros a objetos en almacenamiento dinámico), que a veces es más lento que el acceso a un miembro simple que no sea puntero. El puntero d se usa mucho en las bibliotecas Qt [7] y KDE .
Véase también
Referencias
- ^ Chris McKillop. "Herramientas de programación: punteros opacos". QNX Software Systems . Consultado el 16 de enero de 2019 .
- ^ de 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). "Making Pimpl Easy" (Cómo quitarse los granos fácilmente). Diario del Dr. Dobb . Consultado el 7 de mayo de 2008 .
- ^ Herb Sutter. La alegría de los granos (o más sobre el lenguaje del compilador-cortafuegos)
- ^ Robert A. Duff (29 de julio de 2002). "Re: ¿Cuál es su nombre?". Grupo de noticias : comp.lang.ada . Consultado el 11 de octubre de 2007 .
- ^ Uso de un d-Pointer : por qué y cómo KDE implementa punteros opacos
- ^ "D-Pointer". Wiki de Qt . Consultado el 23 de diciembre de 2016 .
Enlaces externos
- El modismo de Pimpl
- Firewalls de compilación o Firewalls de compilación
- El modismo del grano rápido
- Punteros D — KDE TechBase
- Cuando se realiza una operación "XOR" del puntero con un número aleatorio [1] [2], el resultado es un puntero "realmente opaco" [3].
- Cómo hacer que la espinilla salga fácil, Vladimir Batov