Está en la página 1de 6

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 los
constructores 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 valor
double 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 tales
constructores 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