Bienvenidos sean a este post, hoy veremos un tema heredado.
Como mencionamos este es una estructura de datos heredada de C. Este es una version primitiva o primigenia de las clases de C++. A diferencia de las clases este solo contiene variables y no funciones. Veamos un ejemplo de un struct:
struct numeros {
float flotantes;
double dobles;
int enteros;
}
Le pasaremos un nombre que lo identificara y dentro tendremos tres tipos de variables diferentes. A la hora de crearlo, es igual a una clase y para acceder es de la misma manera. Para entender el concepto, vamos a aplicar a un ejemplo:
#include <iostream>
#include <string.h>
struct Coche {
std::string marca;
std::string modelo;
int anio;
char caja;
char tipo;
};
int main()
{
Coche c1;
c1.marca = "VW";
c1.modelo = "GOL";
c1.anio = 1994;
c1.caja = 'M';
c1.tipo = 'N';
std::cout << "Es un " << c1.marca << " " << c1.modelo;
std::cout << " de " << c1.anio << " y su caja es ";
std::cout << (c1.caja == 'A' ? "automatica.\n" : "manual.\n");
return 0;
}
Tendremos un struct para crear un objeto, como si fuera una clase. En este caso, importaremos a la libreria string.h para poder usar el tipo string. Lo primero que haremos es crear al struct. Este contendra cinco variables para almacenar varios datos que representan al coche. Estos son la marca, modelo, el año de fabricacion, el tipo de caja y el tipo de motor. En el main, primero crearemos el objeto desde el struct y lo denominaremos como c1. Para asignar los distintos valores, simplemente usamos el objeto seguido de la variable y le asignamos el valor correspondiente. Para los dos ultimos casos solo usamos un caracter que lo identifique. Para el caso de la caja, la letra A representa a la caja automatica y la M para la caja manual. Para el tipo podemos usar tres letras: N para naftero, D para diesel o gasolero (como se denomina en Argentina), y E para electrico. Cargamos los distintos valores para nuestro «coche» y luego procedemos a mostrarlo en consola. Para el caso del tipo de caja usamos un operador condicional donde en base a la letra asignada mostraremos un mensaje u otro. Compilemos y veamos como es la salida:
$ ./struct
Es un VW GOL de 1994 y su caja es manual.
$
Como pueden ver ahora tenemos un objeto para representar un coche. Y si bien este no es similar a una clase, podemos imitarla en su conducta y acciones. Para ello, modificaremos el codigo anterior de la siguiente manera:
#include <iostream>
#include <string.h>
struct Coche {
std::string marca;
std::string modelo;
int anio;
char caja;
char tipo;
};
void iniciar(Coche *c, std::string marca, std::string modelo,
int anio = 1976, char caja = 'M', char tipo = 'N') {
c->marca = marca;
c->modelo = modelo;
c->anio = anio;
c->caja = caja;
c->tipo = tipo;
}
void setMarca(Coche *c, const std::string m) {
c->marca = m;
}
std::string getMarca(Coche *c) { return c->marca; }
void setModelo(Coche *c, const std::string m) {
c->modelo = m;
}
std::string getModelo(Coche *c) { return c->modelo; }
void setAnio(Coche *c, const int a) {
if (a < 1886) {
c->anio = 1886;
return;
}
c->anio = a;
}
int getAnio(Coche *c) { return c->anio; }
void setCaja(Coche *c, const char e) {
if (e=='M' || e=='A') {
c->caja = e;
return;
}
c->caja = 'M';
}
std::string getCaja(Coche* c) {
std::string caja;
switch (c->caja)
{
case 'A':
caja = "Automatica";
break;
case 'M':
caja = "Manual";
break;
default:
caja = "Manual";
}
return caja;
}
void setTipo(Coche* c, const char t){
if (t=='N' || t=='D' || t=='E') {
c->tipo = t;
return;
}
c->tipo = 'N';
}
std::string getTipo(Coche* c) {
std::string tipo;
switch(c->tipo)
{
case 'N':
tipo = "Naftero";
break;
case 'D':
tipo = "Diesel";
break;
case 'E':
tipo = "Electrico";
break;
default:
tipo = "Naftero";
}
return tipo;
}
int main()
{
Coche c1;
iniciar(&c1, "VW", "GOL", 1994);
std::cout << "Es un " << getMarca(&c1) << " " << getModelo(&c1);
std::cout << " de " << getAnio(&c1) << ", su caja es ";
std::cout << getCaja(&c1) << " y su motor es ";
std::cout << getTipo(&c1) << std::endl;
return 0;
}
En esta ocasion, agregamos nuevas funciones para distintas acciones en nuestro struct y algunos cambios en el main. Primero definiremos una funcion llamada iniciar y esta la podemos usar como constructor para iniciar los valores de las variables del struct. Este recibira al objeto del struct, dos valores de tipo string para la marca y el modelo. Despues tenemos tres argumentoss mas para iniciar el valor del año, tipo de caja y tipo de motor. En todos los casos, le asignamos un valor predeterminado en caso de no informarlo. En el bloque asignaremos cada valor a cada variable del objeto. Luego tenemos una serie de funciones que podemos considerar como la mecanica getter y setter.
Las funciones que inician con set se encargan de recibir un valor y asignarlo a la propiedad que corresponde a la funcion. Por otro lado, las que comienzan con get se encargan de devolver el valor con el nombre de la propiedad pero esto nos permite manipular la informacion de mejor manera. Veamos algunos casos. En el caso de la marca y modelo solamente recibimos el puntero del objeto tanto para el get como el set sino que tambien pasamos el valor al set y lo asignamos. En las funciones get lo devolvemos directamente. Para el resto, agregamos mas funcionalidades. Por ejemplo, en el caso de set para el año tenemos un condicional donde verifica si el valor es menor al año 1886, lo establece como valor porque no existen coches por debajo de ese año, por lo menos oficialmente. Si no existiera este condicional, el usuario podria pasar cualquier valor. En cambio, si el valor es mayor lo asignaremos. En el caso de las cajas, tenemos dos posibilidades pero para evitar que se asigne otro valor tambien usamos un condicional. Este verifica si el valor es M o A, si se cumple lo asigna. De lo contrario, siempre se asignara la M, para establecer un valor predeterminado y no se mueva de estos.
Pero que sucede si lo asignamos erroneamente en iniciar? Aqui entra en accion la funcion de getCaja. Porque este tiene un condicional donde evalua los dos posibles valores en caja pero tiene un default. Si el valor no encaja con los anteriores procede a devolver Manual, como si fuera un predeterminado.
En la funcion setTipo hacemos algo similar. Tenemos un condicional donde evalua los tres posibles valores que se pueden usar, en caso de cumplirse alguno procede a asignarlo. En caso contrario, lo ignora y asignamos el valor de N, para indicar que es naftero. En el get volvemos a repetir el procedimiento de getCaja pero ahora con los tres valores posibles, cada uno tendra un texto y es el valor que devolveremos. Tambien tenemos un default, esto para evitar algun inconveniente si se agrego un valor erroneo con la funcion iniciar. Al igual que sucede con las clases, esto evita que se generen errores por informacion ingresada de forma incorrecta. En el main, primero crearemos el objeto del struct y luego usamos a iniciar donde solo pasaremos tres valores: marca, modelo y año. Los faltantes tomara el valor predeterminado. Luego mostraremos un texto con los distintos valores del objeto, observen que agregamos al faltante como era el tipo de motor. Si lo compilan y ejecutan trabajara de la siguiente manera:
$ ./struct
Es un VW GOL de 1994, su caja es Manual y su motor es Naftero
$
Como dijimos ya tenemos algo similar a lo que son las clases pero en realidad es una version primigenia de los mismos. Por que los struct son solamente public y las clases pueden ser public, private y protected. Cada uno con sus pros y contras, asi como tambien las clases tambien poseen la herencia y el polimorfismo, pero eso no significa que faciliten las cosas. es mas la complican bastante como ya vimos anteriormente. Pero en la realidad, cuando las clases pasan a bajo nivel se usan como struct.
Antes de finalizar cabe aclarar, si bien no acepta funciones dentro de su estructura, como hace la clase, si podemos aplicarle modificadores de acceso. Permitiendo tener una parte publica y otra privada. A su vez pueden ser herederas de una clase y compartir ciertos aspectos pero no es recomendable hacer esta mezcla. Pero hay que saber que no generara algo invalido o erroneo. Por ultimo, esto lo vimos simplemente para tenerlo en cuenta porque puede aparecer en algun codigo para facilitar sus tareas.
En resumen, hoy hemos visto a struct, que es, para que sirve, porque es la forma primigenia de las clases, y luego vimos un par de ejemplos para verla en accion y como podemos imitar a una clase. Espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donatión
It’s for site maintenance, thanks!
$1.50
