Curso de C++ (Página 12a)

pagina011 Principal pagina012b

CAPITULO 12a Tipos de variables III: Estructuras

Las estructuras son el segundo tipo de datos estructurados que veremos.

Las estructuras nos permiten agrupar varios datos, aunque sean de distinto tipo, que mantengan algún tipo de relación, y manipularlos todos juntos, con un mismo identificador, o por separado.

Las estructuras son llamadas también muy a menudo registros, o en inglés "records". Y son estructuras análogas en muchos aspectos a los registros de bases de datos. Y siguiendo la misma analogía, cada variable de una estructura se denomina a menudo campo, o "field".

Sintaxis:

struct [<nombre de la estructura>] {

[<tipo> <nombre de variable>[,<nombre de variable>,...]];

.

} [<variable de estructura>[,<variable de estructura>,...];

El nombre de la estructura es un nombre opcional para referirse a la estructura.

Las variables de estructura son variables declaradas del tipo de la estructura, y su inclusión también es opcional. Sin bien, al menos uno de estos elementos debe existir, aunque ambos sean opcionales.

En el interior de una estructura, entre las llaves, se pueden definir todos los elementos que consideremos necesarios, del mismo modo que se declaran las variables.

Las estructuras pueden referenciarse completas, usando su nombre, como hacemos con las variables que ya conocemos, y también se puede acceder a los elementos en el interior de la estructura usando el operador de selección (.), un punto.

También pueden declararse más variables del tipo de estructura en cualquier parte del programa, de la siguiente forma:

[struct] <nombre de la estructura> <variable de estructura>[,<variable de estructura>...];

La palabra "struct" es opcional en la declaración de variables.

Ejemplo:

struct Persona {
   char Nombre[65]; 
   char Direccion[65]; 
   int AnyoNacimiento; 
} Fulanito; 

Este ejemplo declara a Fulanito como una variable de tipo Persona. Para acceder al nombre de Fulanito, por ejemplo para visualizarlo, usaremos la forma:

cout << Fulanito.Nombre; 

Funciones en el interior de estructuras:

C++, al contrario que C, permite incluir funciones en el interior de las estructuras. Normalmente estas funciones tienen la misión de manipular los datos incluidos en la estructura.

Aunque esta característica se usa casi exclusivamente con las clases, como veremos más adelante, también puede usarse en las estructuras.

Dos funciones muy particulares son las de inicialización, o constructor, y el destructor. Veremos con más detalle estas funciones cuando asociemos las estructuras y los punteros.

El constructor es una función 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 operador "~".

Nota: para aquellos que usen un teclado español, el símbolo "~" se obtiene pulsando las teclas del teclado numérico 1, 2, 6, mientras se mantiene pulsada la tecla ALT, ([ALT]+126).

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(); // Declaración del constructor
} Punto1, Punto2;
 
Punto::Punto() {  // Definición del constructor, fuera de la estructura
   x = 0; 
   y = 0; 
} 

Si no usáramos un constructor, los valores de x e y para Punto1 y Punto2 estarían indeterminados, contendrían la "basura" que hubiese en la memoria asignada a estas estructuras durante la ejecución. Con las estructuras éste será el caso más habitual.

Mencionar aquí, sólo a título de información, que el constructor no tiene por qué ser único. Se pueden incluir varios contructores, pero veremos esto mucho mejor y con más 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 capítulos posteriores.

También podemos incluir otras funciones, que se declaran y definen como las funciones que ya conocemos, salvo que tienen restringido su ámbito al interior de la estructura.

Otro ejemplo:

#include <iostream.h>
 
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 cómo 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 algún tratamiento de los datos.

Por supuesto se pueden definir otras funciones y también constructores más elaborados y sobrecarga de operadores. Y en general, las estructuras admiten cualquiera de las características de las clases, siendo en muchos aspectos equivalentes.

Veremos estas características cuando estudiemos las clases, y recordaremos cómo aplicarlas a las estructuras.


pagina011 Principal pagina012b