Está en la página 1de 7

11 Tipos de objetos III: Estructuras

^
Las estructuras son el segundo tipo de datos estructurados que veremos (valga la
redundancia).
Al contrario que los arrays, las estructuras nos permiten agrupar varios datos, que
mantengan algn tipo de relacin, aunque sean de distinto tipo, permitiendo
manipularlos todos juntos, usando un mismo identificador, o cada uno por separado.
Las estructuras son llamadas tambin muy a menudo registros, o en ingls records.
Tienen muchos aspectos en comn con los registros usados en bases de datos. Y
siguiendo la misma analoga, cada objeto de una estructura se denomina a menudo
campo, o field.
Sintaxis:
struct [<identificador>] {
[<tipo> <nombre_objeto>[,<nombre_objeto>,...]];
} [<objeto_estructura>[,<objeto_estructura>,...];
El identificador de la estructura es un nombre opcional para referirse a la estructura.
Los objetos de estructura son objetos declarados del tipo de la estructura, y su
inclusin tambin es opcional. Sin bien, an siendo ambos opcionales, al menos uno de
estos elementos debe existir.
En el interior de una estructura, entre las llaves, se pueden definir todos los elementos
que consideremos necesarios, del mismo modo que se declaran los objetos.
Las estructuras pueden referenciarse completas, usando su nombre, como hacemos
con los objetos que ya conocemos, y tambin se puede acceder a los elementos
definidos en el interior de la estructura, usando el operador de seleccin (.), un punto.
Una vez definida una estructura, es decir, si hemos especificado un nombre para ella,
se puede usar igual que cualquier otro tipo de C++. Esto significa que se pueden
declarar ms objetos del tipo de estructura en cualquier parte del programa. Para ello
usaremos la forma normal de declaracin de objetos, es decir:
[struct] <identificador> <objeto_estructura>
[,<objeto_estructura>...];
En C++ la palabra struct es opcional en la declaracin de objetos, al contrario de lo que
sucede en C, en el que es obligatorio usarla.
Ejemplo:
struct Persona {
char Nombre[65];
char Direccion[65];
int AnyoNacimiento;
} Fulanito;
Este ejemplo define la estructura Persona y declara a Fulanito como un objeto de ese
tipo. Para acceder al nombre de Fulanito, por ejemplo para visualizarlo, usaremos la
forma:
cout << Fulanito.Nombre;
Funciones en el interior de estructuras
^
C++, permite incluir funciones en el interior de las estructuras. Normalmente estas
funciones tienen la misin de manipular los datos incluidos en la estructura, y su uso
est muy relacionado con la programacin orientada a objetos.
Aunque esta caracterstica se usa casi exclusivamente con las clases, como veremos
ms adelante, tambin puede usarse en las estructuras. De hecho, en C++, las
diferencias entre estructuras y clases son muy tenues.
Dos funciones muy particulares son las de inicializacin, o constructor, y el destructor.
Veremos con ms detalle estas funciones cuando asociemos las estructuras y los
punteros.
El constructor es una funcin sin tipo de retorno y con el mismo nombre que la
estructura. El destructor tiene la misma forma, salvo que el nombre va precedido el
smbolo "~".
Nota: para aquellos que usen un teclado espaol, el smbolo "~" se obtiene pulsando
las teclas del teclado numrico 1, 2, 6, mientras se mantiene pulsada la tecla ALT,
([ALT]+126). Tambin mediante la combinacin [Atl Gr]+[4] y un espacio (la tecla [4]
de la zona de las letras, no del teclado numrico).
Veamos un ejemplo sencillo para ilustrar el uso de constructores:
Forma 1:
struct Punto {
int x, y;
Punto() {x = 0; y = 0;} // Constructor
} Punto1, Punto2;
Forma 2:
struct Punto {
int x, y;
Punto(); // Declaracin del constructor
} Punto1, Punto2;

// Definicin del constructor, fuera de la estructura
Punto::Punto() {
x = 0;
y = 0;
}
Si no usramos un constructor, los valores de x e y para Punto1 y Punto2 estaran
indeterminados, contendran la "basura" que hubiese en la memoria asignada a estas
estructuras durante la ejecucin. Con las estructuras ste ser el caso ms habitual, ya
que si necesitamos usar constructores para asignar valores iniciales, ser mucho ms
lgico usar clases que estructuras.
Mencionar aqu, slo a ttulo de informacin, que el constructor no tiene por qu ser
nico. Se pueden definir varios constructores, pero veremos esto mucho mejor y con
ms detalle cuando veamos las clases.
Usando constructores nos aseguramos los valores iniciales para los elementos de la
estructura. Veremos que esto puede ser una gran ventaja, sobre todo cuando
combinemos estructuras con punteros, en captulos posteriores.
Tambin podemos incluir otras funciones, que se declaran y definen como las
funciones que ya conocemos.
Otro ejemplo:
#include <iostream>
using namespace std;

struct stPareja {
int A, B;
int LeeA() { return A;} // Devuelve el valor de A
int LeeB() { return B;} // Devuelve el valor de B
void GuardaA(int n) { A = n;} // Asigna un nuevo valor a A
void GuardaB(int n) { B = n;} // Asigna un nuevo valor a B
} Par;

int main() {
Par.GuardaA(15);
Par.GuardaB(63);
cout << Par.LeeA() << endl;
cout << Par.LeeB() << endl;

return 0;
}
En este ejemplo podemos ver cmo se define una estructura con dos campos enteros, y
dos funciones para modificar y leer sus valores. El ejemplo es muy simple, pero las
funciones de guardar valores se pueden elaborar para que no permitan determinados
valores, o para que hagan algn tratamiento de los datos.
Por supuesto se pueden definir otras funciones y tambin constructores ms
elaborados e incluso, redefinir operadores. Y en general, las estructuras admiten
cualquiera de las caractersticas de las clases, siendo en muchos aspectos equivalentes.
Veremos estas caractersticas cuando estudiemos las clases, y recordaremos cmo
aplicarlas a las estructuras.
Inicializacin de estructuras
^
De un modo parecido al que se inicializan los arrays, se pueden inicializar estructuras,
tan slo hay que tener cuidado con las estructuras anidadas. Por ejemplo:
struct A {
int i;
int j;
int k;
};

struct B {
int x;
struct C {
char c;
char d;
} y;
int z;
};

A ejemploA = {10, 20, 30};
B ejemploB = {10, {'a', 'b'}, 20};
Cada nueva estructura anidada deber inicializarse usando la pareja correspondiente
de llaves "{}", tantas veces como sea necesario.
Asignacin de estructuras
^
La asignacin de estructuras est permitida, pero slo entre objetos del mismo tipo de
estructura, (salvo que se usen constructores), y funciona como la intuicin nos dice
que debe hacerlo.
Veamos un ejemplo:
struct Punto {
int x, y;
Punto() {x = 0; y = 0;}
} Punto1, Punto2;

int main() {
Punto1.x = 10;
Punto1.y = 12;
Punto2 = Punto1;
}
La lnea Punto2 = Punto1; equivale a Punto2.x = Punto1.x; Punto2.y =
Punto1.y;.
Quizs te hayas quedado intrigado por el comentario anterior, que adelantaba que se
pueden asignar estructuras diferentes, siempre que se usen
losconstructores adecuados.
Esto, en realidad, se puede extender a cualquier tipo, no slo a estructuras. Por
ejemplo, definiendo el constructor adecuado, podemos asignar un entero a una
estructura. Veamos cmo hacer esto.
Hasta ahora, los constructores que hemos visto no usaban argumentos, pero eso no
significa que no puedan tenerlos.
Crearemos como ejemplo, una estructura para manejar nmeros complejos. Un
nmero complejo est compuesto por dos valores reales, el primero contiene lo que se
llama la parte real y el segundo la parte imaginaria.
struct complejo {
double real;
double imaginario;
};
Esta estructura es suficiente para muchas de las cosas que podemos hacer con nmeros
imaginarios, pero aprovechando que podemos crear funciones, podemos aadir
algunas que hagan de una forma ms directa cosas que de otro modo requieren aadir
cdigo externo.
Por ahora nos limitaremos a aadir unos cuantos constructores. El primero es el ms
lgico: un constructor por defecto:
struct complejo {
complejo() { real=0; imaginario = 0; }
double real;
double imaginario;
};
Este construtor se usar, por ejemplo, si declaramos un array:
complejo array[10];
El constructor por defecto ser llamado para cada elemento del array, aunque no
aparezca tal llamada en ningn punto del programa.
Otro constructor nos puede servir para asignar un valor a partir de dos nmeros:
struct complejo {
complejo() { real=0; imaginario = 0; }
complejo(double r, double i) { real=r; imaginario = i; }
double real;
double imaginario;
};
Mediante este constructor podemos asignar valores inciales en la declaracin:
complejo c1(10.23, 213.22);
Los nmeros reales se consideran un subconjunto de los imaginarios, en los que la
parte imaginaria vale cero. Esto nos permite crear otro constructor que slo admita un
valor real:
struct complejo {
complejo() { real=0; imaginario = 0; }
complejo(double r, double i) { real=r; imaginario = i; }
complejo(double r) { real=r; imaginario = 0; }
double real;
double imaginario;
};
Este constructor nos permite, como en el caso anterior, inicializar un valor de un
complejo en la declaracin, pero tambin nos permite asignar un valordouble a un
complejo, y por el sistema de promocin automtico, tambin podemos asignar valores
enteros o en coma flotante:
complejo c1(19.232);
complejo c2 = 1299.212;
int x = 10;
complejo c3 = x;
Este tipo de constructores se comportan como conversores de tipo, nada nos impide
crear constructores con cualquier tipo de parmetro, y talesconstructores se podrn
usar para convertir cualquier tipo al de nuestra estructura.
Arrays de estructuras
^
La combinacin de las estructuras con los arrays proporciona una potente herramienta
para el almacenamiento y manipulacin de datos.
Ejemplo:
struct Persona {
char Nombre[65];
char Direccion[65];
int AnyoNacimiento;
} Plantilla[200];
Vemos en este ejemplo lo fcil que podemos declarar el array Plantilla que contiene
los datos relativos a doscientas personas.
Podemos acceder a los datos de cada uno de ellos:
cout << Plantilla[43].Direccion;
O asignar los datos de un elemento de la plantilla a otro:
Plantilla[0] = Plantilla[99];
Estructuras anidadas
^
Tambin est permitido anidar estructuras, con lo cual se pueden conseguir
superestructuras muy elaboradas.
Ejemplo:
struct stDireccion {
char Calle[64];
int Portal;
int Piso;
char Puerta[3];
char CodigoPostal[6];
char Poblacion[32];
};

struct stPersona {
struct stNombre {
char Nombre[32];
char Apellidos[64];
} NombreCompleto;
stDireccion Direccion;
char Telefono[10];
};
...
En general, no es una prctica corriente definir estructuras dentro de estructuras, ya
que tienen un mbito local, y para acceder a ellas se necesita hacer referencia a la
estructura ms externa.
Por ejemplo para declarar un objeto del tipo stNombre hay que utilizar el operador de
acceso (::):
stPersona::stNombre NombreAuxiliar;
Sin embargo para declarar un objeto de tipo stDireccion basta con declararla:
stDireccion DireccionAuxiliar;

También podría gustarte