Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Declaración de Estructuras
Declaración de Estructuras
Sinopsis
Lo mismo que con el resto de las clases, el proceso de usar una estructura C++ comprende
en realidad tres pasos: definir la clase; crear un objeto, e iniciar el objeto.
Definir la clase
En contra de lo que ocurre con el resto de los tipos, que están pre-definidos en el lenguaje.
Por ejemplo, al declarar char ch; ya se sabe exactamente que cosa es ch, en este caso hay
que definir previamente el tipo. Los tipos estructura se declaran mediante la palabra clave
struct. Sería algo así como:
struct Punto;
struct Punt2 {int x; int y; int z; };
La primera sentencia es una declaración incompleta (ver más abajo); la segunda es una
definición completa de una nueva clase tipo struct denominado Punt2; tiene tres
componentes perfectamente definidos (tres int: x, y, z respectivamente). Como puede
verse, los componentes se determinan de forma análoga a los parámetros de las funciones,
determinando tipo y nombre. Aquí es imprescindible el punto y coma ";" para separar los
miembros (sin olvidar poner otro después del último).
2.1 Ya hemos señalado que en C++ las estructuras son un tipo de clases; entonces, si
nos referimos a la terminología de la POO diríamos que en esta fase estamos
definiendo la clase. El conjunto de declaraciones dentro de los corchetes {...; ...; ...; }
declara los nombres y tipos de sus miembros. Los miembros pueden ser de cualquier
tipo con una excepción:
2.2 Un miembro no puede ser la estructura que se declara porque daría lugar a una
declaración circular (lo definido está dentro de su definición). Ejemplo:
2.3 Uno, o varios, de los miembros puede ser un puntero a la estructura que se está
declarando. Ejemplo:
2.4 También es posible que los miembros de una estructura sean a su vez estructuras
previamente definidas, dando lugar a estructuras anidadas. Por ejemplo:
struct Punto {
int x; int y;
};
struct Linea {
struct Punto p1;
struct Punto p2;
} c1;
declara Linea como un tipo struct con dos miembros, cada uno de los cuales es un tipo
struct Punto.
Nota: en C, un miembro no puede ser del tipo "función devolviendo...". Es decir, las
funciones no pueden ser miembros de la estructuras C (de lo contrario serían clases). En
cambio, sí están admitidos los "punteros a función devolviendo..." (ya que son
variables, no métodos). Las estructuras C++ sí pueden incluir funciones miembro (de
hecho son clases), además, en C++ la palabra struct puede omitirse.
2.5 Es importante tener en cuenta que, en este punto (definición), solo está permitido
señalar tipo y nombre de los miembros, sin que se pueda efectuar ninguna asignación;
ni aún en el caso de que se trate de una constante [1]. Por ejemplo, las definiciones que
siguen serían ilegales, pues todas implican una asignación en la definición del segundo
miembro:
.
Crear un objeto (instanciar la clase)
Un segundo paso es declarar una variable como perteneciente al nuevo tipo. Del mismo
modo que para declarar una variable ch como de tipo char declarábamos: char ch;, en este
caso, para declarar una variable st como estructura tipo punto se utiliza:
En C++ no es necesario señalar que Punto es una estructura (suponemos que ya lo sabe el
compilador por las sentencias anteriores), de forma que si no existe ninguna otra variable
punto en el mismo ámbito de nombres, no hay ambigüedad y se puede poner directamente:
3.1 Advertir que cada declaración de (tipo de) estructura introduce un nuevo tipo,
distinto de los demás (una nueva clase), de forma que las declaraciones:
struct StA {
int i,j;
} a, a1;
struct StB {
int i,j;
} b;
definen dos tipos de estructura distintas: StA y StB; los objetos a y b1 son del tipo StA,
pero a y b son de tipo distinto.
Desde la óptica de la POO la frase anterior se enunciaría como sigue: "definen dos clases
distintas, StA y StB; los objetos a y b1 son instancias de StA, pero b lo es de la clase StB.
Por tanto, a y b son objetos de tipo distinto.
3.2 De la misma forma que ocurre con el resto de variables, puede declararse más de un
elemento en la misma sentencia:
sin embargo, de una variable de tipo estructura no es posible derivar nuevas variables, es
decir no es lícita la sentencia que sigue (utilizando la terminología de C++ lo
enunciaríamos diciendo: de un objeto no puede instanciarse otro objeto).
struct p1, p11, p12, p13,... p1n; // NO!!
Iniciar el objeto
Un tercer paso es inicializar dicha variable. Del mismo modo que para iniciar ch se
realizaba una asignación del tipo: ch = 'x', en este caso se utiliza la asignación (análoga a la
de matrices):
Una vez definido el nuevo tipo, pueden declararse punteros y matrices de estructuras de
dicho tipo. Por ejemplo:
La segunda línea declara que st es una estructura de tipo stA; que pst es un puntero a dicho
tipo, y que arst es un array de 10 estructuras tipo stA.
4.1 Como se verá a continuación , es posible incluso declarar estructuras sin asignar un
nombre al tipo correspondiente. Por ejemplo:
Los nombres de tipos de estructura comparten el espacio de nombres con las uniones y
enumeraciones (las enumeraciones dentro de una estructura están en un espacio de
nombres diferente). Ver L.4 y L.11 en el ejemplo.
La consecuencia es que dentro del mismo ámbito, los nombres de estructuras y uniones
deben ser únicos (ambos comparten el espacio de nombres de clases), aunque no hay
inconveniente que compartan los nombres con los miembros de los otros tres espacios: El
de etiquetas; el de miembros (de clases) y el de enumeraciones [3].
5.1 Ejemplo
goto s;
...
s: // L.3 Etiqueta
struct s { // L.4 OK: nombres de tipo_de_estructura y etiqueta en
// espacios diferentes
int s; // L.6 OK: nombres miembro de estructura en espacio privado
float s; // L.7 ILEGAL: nombre de miembro duplicado
} s; // L.8 OK: nombre_de_estructura en espacio diferente de
// nombre de etiqueta (L.3) y de tipo_de_estructura (L4)
// En C++, esto solo es posible si s no tiene un constructor
union s { // L.11 ILEGAL: nombre duplicado con el de tipo s (L.4)
int s; // L.12 OK: nuevo espacio de miembros
float f;
} f; // L.14 OK: espacio diferente que el de miembros (ver L.8)
struct t {
int s; // L.16 OK: nuevo espacio de miembros
...
} s; // L.18 ILEGAL: nombre duplicado con el de estructura s (L8)
Declaraciones incompletas
1. Hay que advertir que en C++ es muy frecuente utilizar typedefs en la declaración de
estructuras. De hecho, los ficheros de cabecera de los compiladores C++ están
repletos de ellos. Es muy frecuente que utilicen expresiones como [4]:
typedef struct {
unsigned char *curp; // Current active pointer
unsigned char *buffer; // Data transfer buffer
int level; // fill/empty level of buffer
int bsize; // Buffer size
unsigned short istemp; // Temporary file indicator
unsigned short flags; // File status flags
wchar_t hold; // Ungetc char if no buffer
char fd; // File descriptor
unsigned char token; // Used for validity checking
} FILE; // This is the FILE object
#include <stdio.h>
int main(void) {
FILE *in, *out; // define punteros a estructuras FILE
...
Sin embargo, dentro del mismo ámbito de nombres, C++ no permite que una estructura (o
clase) tenga el mismo nombre que un typedef declarado para definir un tipo diferente.
Ejemplo:
Tipos anónimos
Es posible crear un typedef al mismo tiempo que se declara una estructura, con o sin
nombre, como se ve en los ejemplos. Generalmente no se necesitan un typedef y un
nombre al mismo tiempo, ya que cualquiera de ellos sirve para las declaraciones.
Cuando son miembros de clases, las estructuras y uniones anónimas son ignoradas durante
la inicialización.
Nota: el ANSI C++ solamente permite estructuras anónimas que declaren un objeto. Por su
parte, el ANSI C no permite estructuras anónimas, y el compilador C++ de Borland permite
varios tipos de estructuras anónimas que extienden el estándar ANSI.
8.1 Debido a que no hay propiedades de instancia, la sintaxis C++ para las estructuras
anónimas no permite referenciar un puntero this. Por consiguiente, mientras que una
estructura C++ puede tener funciones miembro, las estructuras anónimas C++ no pueden
tenerlas. Los miembros de las estructuras anónimas pueden ser accedidos directamente en
el ámbito en que las estructuras han sido declaradas sin la necesidad de utilizar la sintaxis
x.y o p->y. Por ejemplo:
struct my_struct {
int x;
struct {
int i;
};
inline int func1(int y) { return y + i + x; }
} S;
int main() {
S.x = 6; S.i = 4;
int y = S.func1(3);
printf(“y is %d“, y);
return 0;
}
Borland C++ permite estructuras anónimas y que no sean usadas para declarar un objeto o
cualquier otro tipo. Tienen la forma que se indica:
struct { lista-de-miembros };
Las estructuras anónimas pueden ser anidadas, es decir, declaradas dentro de otra
estructura, unión o clase. En estos casos, la estructura externa debe tener nombre. Por
ejemplo:
struct my_struct {
int x;
struct { // estructura anónima anidada dentro de my_struct
int i;
};
inline int func1(int y);
} S;
struct Direccion {
char calle[25];
int numero;
};
struct Persona {
char nombre[35]
struct Direccion; // estructura huérfana
} candidato; // una instancia de Persona
candidato.numero = 10;
[1] Si nos referimos a C++, se podrían hacer asignaciones iniciales, pero a través del
constructor de la clase.
[3] No confundir los nombres de las enumeraciones con los nombres de los enumeradores.