2010-07-23 9 views
5

Una forma de piratear forma limitada de polimorfismo en C es hacer algo como esto:Semi-herencia en C: ¿Cómo funciona este fragmento?

typedef struct { 
    int x; 
} base; 

typedef struct { 
    base super; 
    int y; 
} derived; 

Ahora se puede hacer referencia a una instancia derivada como una instancia de base, dependiendo de cómo la variable está echada, es decir:

derived my_derived; 
my_derived.y = 10; 
my_derived.super.x = 20; 
//will print 10 
printf("%d", (&my_derived)->y); 
//will print 20 
printf("%d", ((base*)(&my_derived))->x); 

Así que mi pregunta es, ¿cómo funciona esto exactamente? ¿Es porque cuando lo haces como base y haciendo referencia a una variable, estás haciendo referencia al miembro int 'x' como el desplazamiento desde el inicio de la estructura 'base'? Esto es lo único que se me ocurre, cualquier ayuda sería apreciada.

Gracias mucho!

Respuesta

11

En una estructura, puede haber bytes de relleno sin nombre entre los elementos de datos o al final de la estructura, pero no al principio. Por lo tanto, se garantiza que la dirección del primer elemento de datos de un objeto struct-type sea la misma que la dirección del objeto struct-type.

Por lo tanto, en su ejemplo, la dirección de my_derived es la misma que la dirección de my_derived.super.

+2

1 Este es en realidad garantizada por la especificación C. – bta

1

¿Es porque cuando lo haces como base y haciendo referencia a una variable, estás haciendo referencia al miembro int 'x' como el desplazamiento desde el inicio de la estructura 'base'?

Sí. Esta técnica a veces se conoce como "tipo de juego de palabras".

Esto se utiliza en la biblioteca estándar POSIX; por ejemplo, en struct sockaddr. Por lo general, declaras uno como sockaddr_storage, lo pasas como sockaddr y lo manipulas como sockaddr_in o _in6, dependiendo del tipo de dirección que esté realmente almacenada dentro de él.

2

Una estructura es una memoria de área de byte que el compilador conoce su estructura, es decir, qué variables declaras dentro.

Por ejemplo, puede declarar una estructura:

struct st { 
    int number; 
}; 

struct st n; 
n.number = 10; 
printf("n=%i\n", n.number); 

Pero se puede cambiar el comportamiento del compilador, por ejemplo declarar un puntero a char sobre su estructura:

char *c = (char*)&n; 
printf("char c=%c\n", c[0]); 

Ésta es una declaración legal . Luego puede cambiar en cualquier momento la estructura de esa zona de memoria. Lo único importante es la dirección de memoria de su estructura declarada.

En su ejemplo, cuando se declare la estructura derivada de la reserva del programa un área de memoria para asignar el stucture derivada, pero la forma en que el compilador de ver esta área se puede cambiar en cualquier momento:

struct derived my_derived; 
struct base *b = (struct base*)&my_derived; 

b->x = 20; 
my_derived.y = 10; 
printf("x=%i y=%i\n", my_derived.base.x, my_derived.y); 

En este caso b y & my_derived comparten la misma área de memoria, solo cambia cómo el compilador "ve" esta área.

El uso del "tipo de juego de palabras" es la base de la simulación de herencia de oop en C, una programación de programación no sola.

que utilizan esta técnica en mis proyectos: oop4c

Cuestiones relacionadas