Los miembros privados en las estructuras de C
Esta semana, aquí en el trabajo tenía más prueba de que es un paradigma de programación completamente independiente del lenguaje, es decir, no por el hecho de que usted es la programación en C + +, compilar con g + +, su código será orientado a objetos tan poco, si se programa en ANSI C el código será necesariamente estructurados o será incapaz de programación orientada a objetos.
Que estoy leyendo, Orientación a Objetos en ANSI C?
Sí y no!
Cosas como la herencia, polimorfismo y la sobrecarga son complicadas de hacer / emular en C, pero usted puede programar utilizando un estilo que se comporta de manera similar a la orientación a objetos. El libdfb está escrito en C, pero "orientado a objetos", de manera que crear, manipular para destruir los elementos que se comportan de manera muy similar a los objetos.
Aquí en el trabajo, tenemos un sistema de abstracción de hardware en C que se conecta con una interfaz gráfica de usuario en C + +. La capa más baja en C también fue escrito (y muy bien escrito, por la forma) con estas técnicas, que simula una orientación a objetos. Una de estas técnicas, me llamó la atención mediante el uso de una de las notas al pie de los libros de C.
Al compilar código en C, cada símbolo sólo es visible dentro de la unidad de compilación en la que se declaró, a menos que se declaró de nuevo en otras unidades, como externa. Así, se puede "esconder" algunos de los símbolos dentro de la unidad de compilación, haciéndolos inaccesibles para el mundo exterior. Tenemos con este paquete.
Una unidad de compilación es el conjunto de archivos que, después de pre-tratamiento y compilación de generar un código de objeto único. Básicamente (pero no exactamente), se puede tomar como la compilación de cada unidad de ejecución del archivo de código fuente (*. c, *. cpp. Etc). Para más detalles sobre los pasos de compilación de C y C + + se pueden encontrar en la Caloni blog.
Usando esta información, podemos crear una estructura en ANSI C, en la que sus miembros internos son "privadas". La magia está en la definición de los miembros de la trampa dentro de la unidad de compilación y crear métodos de acceso para estos miembros. Para ello se utilizan las notas que nos muestran la diferencia entre la declaración y la definición de los elementos en C:
Declaración o manifiesto: el compilador presenta un identificador sin decir mucho acerca de su significado, o indicar al compilador que el identificador es XXX, pero se sabe poco acerca de lo que él representa.
Por ejemplo,
a ; extern int a; void ) ; bla (void); struct st_date;
Definición y ejecución: le indica al compilador que el identificador es determinado, tales como la cantidad de memoria debe asignarse a la misma y cuál es la dirección de memoria donde se puede encontrar, entre otras cosas.
Por ejemplo,
int a; void ) { /* Do anything. bla (void) (/ * hacer nada. * /) /* Some members. st_date struct (/ * Algunos miembros. * /)
Cuando hablamos de las estructuras y tipos, sin establecer el compilador no tiene manera de asignar memoria para ellos porque no se sabe nada sobre la cantidad de espacio que una variable de ese tipo de necesidad. Por otro lado, a veces sin la declaración, el vinculador no puede saber que existe ese símbolo.
Cuando declaramos una estructura en una cabecera, por lo general también definir sus miembros no existe y cada vez que agregar este encabezado a una fuente de la nuestra, hemos incluido en la unidad de compilación como la fuente de esa declaración como la definición de esta estructura, lo que hace a los miembros del público interinstitutionalcollaboration a esta unidad de compilación. Esto nos permite tener acceso a sus miembros directamente.
Si separamos la declaración de la definición, único símbolo que representa la estructura disponible, pero no de sus miembros. Por lo tanto, cualquier intento de acceso directo a un miembro, generará un error de compilación. Un efecto secundario interesante es que como el compilador no sabe nada sobre el tamaño de la estructura, no puede directamente establecer una variable de la estructura, sólo un puntero a él, porque los punteros son todos del mismo tamaño y el compilador sólo necesita el nombre del símbolo escribir para crear el puntero.
Luego tenemos el encabezado mytype.h algo como esto:
# Ifndef MY_TYPE_H # Define MY_TYPE_H / * El typedef no es sólo seguir repitiendo la palabra estructura. * / / * La declaración es sólo las palabras: * / / * Struct _MYTYPE * / typedef struct my_type _MYTYPE; my_type ** ) ; create_my_type void (my_type **); my_type ** ) ; destroy_my_type void (my_type **); my_type * , int ) ; set_data void (my_type *, int); my_type * ) ; get_data int (my_type *); my_type * , const char * ) ; set_text void (my_type *, const char *); get_text ( my_type * ) ; char * get_text (my_type *); # Endif
Aplicación mytype.c:
# Include "mytype.h" # Include <stdio.h> # Include <stdlib.h> # Include <string.h> /* Aqui fica a definição da estrtura. _MYTYPE Struct (/ * Esta es la definición de estrtura. * / /* Somente depois disso é que o com- */ int data; / * Sólo después de que, con-* / 21 ] ; /* pilador vai saber como alocá-la. texto int [21], / * pilador sabrá cómo asignarlo. * / /* Tente um sizeof(my_type) no main. ), / * Pruebe un sizeof (my_type) en el principal. * / my_type ** my_ptr ) { /* some code... create_my_type void (my_type ** my_ptr) (/ * Código ... * /) my_type ** my_ptr ) { /* some code... destroy_my_type void (my_type ** my_ptr) (/ * Código ... * /) my_type * my_ptr , int d ) { /* some code... set_data void (my_type * my_ptr, int d) (/ * Código ... * /) my_type * my_ptr ) { /* some code... get_data int (my_type * my_ptr) (/ * Código ... * /) my_type * my_ptr , const char * text ) { /* some code... set_text void (my_type * my_ptr, const char * text) (/ * Código ... * /) get_text ( my_type * my_ptr ) { /* some code... char * get_text (my_type * my_ptr) (/ * Código ... * /)
El ejemplo de código fuente completo se puede encontrar aquí.
Debido a que no se puede crear variables de este tipo, se define un "constructor" y un "destructor".
Los intentos de acceso directo a los miembros de generar error de compilación:
private-struct-members$ gcc -o teste mytype.h mytype.c main.c user @ host: ~ / privado struct miembros $ gcc-o test main.c mytype.h mytype.c main.c: En la función 'main': main.c: 22: error: puntero eliminación de referencias al tipo incompleto private-struct-members$ user @ host: ~ / privado struct miembros $
Así, con un poco de creatividad y con los conceptos de lenguaje y de la paradigmas, es posible aplicar códigos realmente interesante. En este ejemplo tonto, no podría haber sido clara la utilidad de forzar a un paquete de emulación o el uso de constructor / destructor en C, pero en sistemas en donde las circunstancias no permiten que un C + +, o la complejidad tiende a alcanzar niveles críticos, tales técnicas muestra de gran valor. En nuestro caso, esta técnica específicamente permitido un programador experimentado, no hizo todo el proyecto, descubrió que su intento de acceso directo a un miembro de una estructura, fue contexto inapropiado. Sin ella, una lógica cabuloso error que aparecen sólo en tiempo de ejecución, haciendo que el software probablemente explotar en la cara del cliente.
Enlaces útiles (o no ...):
http://www.directfb.org
http://www.caloni.com.br
http://www.numaboa.com.br/informatica/c/
Libro de Desarrollo del Kernel de Linux
Comentarios
7 Respuestas a "Los miembros privados en las estructuras de C"
Deje una contestación



¿Dónde puedo descargar el código fuente?
http://blabos.org/blog/wp-content/uploads/2008/02/stopwatch.zip
Buenas noches,
Gracias por su atención.
He estado cambiando el servidor de blog y algunos enlaces terminó siendo roto. Voy a resolverlo.
Abrazos
Según lo prometido, ahí
Abrazos
Quiero decir, aquí:
http://src.blabos.org/blog/posts/17/stopwatch.zip
Es hora de publicar algo nuevo eh AHHuahuAHUahuA
Bruja Sí, tienes razón, pero tá osso ...
Afortunadamente, tengo algo en el horno
Abrazos
También puede ocultar las funciones de las unidades de elaboración externa declarar con estática - Esto es también cierto para las variables globales. Así, la unidad externa no se sabe de la existencia y la función estática evitar que se declaren como extern en otro archivo.