Anuncios

Bienvenidos sean a este post, hoy veremos otro tema relacionado a las clases.

Anuncios

En el post anterior vimos las distintas formas de utilizar a nuestras clases y como crear objetos desde las mismas. Pero el ultimo codigo fue demasiado complejo y poco practico. En este post hablaremos sobre los archivos de encabezado que nos permitiran declarar codigo para ser utilizado en diferentes codigos. Estos archivos siempre llevan la extension .h y en ella almacenaremos las declaraciones o las definiciones. Por lo general, en ella se almaacenan las declaraciones y en otro las definiciones. Tomemos el ultimo caso que vimos en el post anterior.

Anuncios

Lo primero que haremos sera crear un nuevo directorio para trabajarlo aparte. Dentro de este directorio crearemos otro directorio con el nombre de libs y en este crearemos un archivo con el nombre de Perro.h y le agregaremos el siguiente codigo:

libs/Perro.h

class Perro
{
public:
        Perro(int, int);
        ~Perro();
        void Ladrar();
        void setEdad(int);
        int getEdad();
        void setPeso(int);
        int getPeso();
        void setAltura(int);
        int getAltura();
private:
        int edad;
        int peso;
        int altura;
};
Anuncios

En este archivo solo tenemos la declaracion de la clase. Observen que solo usamos los prototipos, si ven el codigo del post anterior notaran que ya no definimos al constructor y destructor sino que utilizamos prototipos para ambos. Como no tenemos ninguna accion, no necesitamos incluir ninguna libreria sino solamente la declaracion de la clase y/o todas las necesarias. Nuestro siguiente paso sera la creacion de otro archivo en libs con el nombre de Perro.cpp y le agregaremos el siguiente codigo:

libs/Perro.cpp

#include "Perro.h"
#include <iostream>

Perro::Perro(int e, int p) {
        std::cout << "Iniciando constructor" << std::endl;
        edad = e;
        peso = p;
}

Perro::~Perro() {
        std::cout << "Destructor invocado" << std::endl;
}

void Perro::Ladrar() {
        std::cout << "Guau!!!" << std::endl;
}

void Perro::setEdad(int e) {
        edad = e;
}

int Perro::getEdad() {
        return edad;
}

void Perro::setPeso(int p) {
        peso = p;
}

int Perro::getPeso() {
        return peso;
}

void Perro::setAltura(int a) {
        altura = a;
}

int Perro::getAltura() {
        return altura;
}
Anuncios

Vamos con la primera curiosidad que es la inclusion del archivo anterior mediante #include. Como mencionamos en este post, cuando pasamos entre comillas el archivo es para indicarle que es propio y debe buscarlo donde le indicamos. En este caso, al estar en el mismo directorio solamente nos alcanza con el nombre. Luego incluimos a la libreria de siempre, para luego pasar a la definicion de los metodos de la clase del otro archivo. Analicemos la definicion del constructor:

Perro::Perro(int e, int p) {
        std::cout << "Iniciando constructor" << std::endl;
        edad = e;
        peso = p;
}
Anuncios
Anuncios

Primero pasamos a la clase seguido del operador de resolucion de ambito. Esto al igual que vimos en el post anterior, es para indicarle donde esta correctamente ubicado y enlazarlo con dicha declaracion. Basicamente, recibe dos valores para asignarlos a las propiedades privadas edad y peso, y a su vez mostramos un mensaje para indicar que se llamo al constructor. Luego tenemos la definicion del destructor, este es igual que el constructor donde debemos pasar solamente la clase seguido del nombre del destructor y en este solo tendremos un mensaje para indicar que fue invocado. Luego, tenemos las distintas definiciones de cada uno de los metodos de la clase, analicemos uno:

void Perro::setEdad(int e) {
        edad = e;
}
Anuncios
Anuncios

Primero siempre ira el tipo de dato, luego pasaremos primero el nombre de la clase donde esta declarada seguido del operador de resolucion de ambito y despues recien el nombre del metodo, si establecimos argumentos los pasaremos con el mismo tipo de la declaracion y dentro iran las instrucciones del metodo. En este caso, recibimos un solo valor y este lo usaremos para establecer el valor en la propiedad edad. En todos los denominados con set se utilizan para esta accion. En cambio todos los iniciados con get tienen el tipo de dato que devuelven por delante y la propiedad especifica. En todos los casos hacemos lo mismo, especificamos la clase, recibe un valor (si es el caso), lo asigna o lo deuelve por cada una de las propiedades. Con esto ya tenemos nuestra primer «libreria» creada, solo nos resta implementarla y para ello salimos del directorio libs y creamos un nuevo archivo con el nombre de clases.cpp y le agregaremos el siguiente codigo:

clases.cpp

#include <iostream>
#include "libs/Perro.h"

int main()
{
        Perro arturo(10,35);
        std::cout << "Edad Arturo: " << arturo.getEdad() << std::endl;
        std::cout << "Peso Arturo: " << arturo.getPeso() << std::endl;
        arturo.Ladrar();

        return 0;
}
Anuncios

Primera curiosidad, incluimos al archivo con la extension .h pero le pasamos el directorio donde esta ubicado, recuerden que en las comillas debemos usar el path correcto, y luego simplemente creamos un objeto de la clase, le establecemos los valores con el constructor, los mostramos mediante los metodos correspondientes y por ultimo llamamos al metodo Ladrar. Como pueden ver tenemos un codigo mas simple y todas nuestras tareas se encuentran fuera de este. Lo bueno de trabajar de esta manera es que ante cualquier error o eventualidad estara en un archivo especifico y no tendremos que ver miles de miles de lineas para descubrirlo. Pero esto tambien cambia la forma de compilarlo, veamos como es:

$ g++ clases.cpp libs/Perro.cpp -o clases
Anuncios

Ahora, al momento de compilarlo debemos pasar todos los archivos .cpp que tengamos en el proyecto. Esto es asi porque debemos enlazar todos los archivos .obj que se generen con el enlazador. En este caso, es una opcion simple porque tenemos un solo archivo adicional pero podemos usar comodines. Veamos el siguiente comando:

$ g++ clases.cpp libs/*.cpp -o clases
Anuncios

Este agregara todos los archivos .cpp que esten en el directorio libs, facilitando nuestra tarea. Compilemoss y ejecutemos para ver como trabaja:

$ ./clases
Iniciando constructor
Edad Arturo: 10
Peso Arturo: 35
Guau!!!
Destructor invocado
$
Anuncios

Como pueden ver funciono perfectamente, no genero ningun problema y tenemos un codigo mejor distribuido y mas simple de analizar, siempre comparandolo con el visto al final del post anterior. Esto es lo basico de un archivo de encabezado pero podemos agregar un tema mas como es el guardian para #include, para ello debemos tomar el codigo de Perro.h y modificarlo de la siguiente manera:

libs/Perro.h

#pragma once
#ifndef CLS_PERRO
#define CLS_PERRO

class Perro
{
public:
        Perro(int, int);
        ~Perro();
        void Ladrar();
        void setEdad(int);
        int getEdad();
        void setPeso(int);
        int getPeso();
        void setAltura(int);
        int getAltura();
private:
        int edad;
        int peso;
        int altura;
};

#endif
Anuncios
Anuncios

Al inicio agregaremos a #pragma once, esta es una directiva de preprocesador y se utiliza principalmente para que el codigo fuente del archivo donde se asigna sea incluido una sola vez. Luego tenemos un condicional donde verifica si no esta definida la constante CLS_PERRO, En caso de ser verdadero, define la constante y luego accedemos al codigo en este condicional, este sigue siendo el mismo, y por ultimo tenemos el final del condicional. Este es el guardian de #include. Porque este tambien impedira que volvamos a cargar este codigo, dado que una vez definida la constante ya no se cumplira la condicion y lo omitira. Si lo compilan nuevamente, veran que sigue funcionando de la misma manera pero ahora con la salvedad de asegurarnos que esta clase sea incluida una sola vez. Veamos como quedo la estructura de nuestro programa:

$ tree .
.
├── clases
├── clases.cpp
└── libs
    ├── Perro.cpp
    └── Perro.h

2 directories, 4 files
$
Anuncios

En resumen, hoy hemos visto a los archivos de encabezado, header files, que es, para que sirve, como es su sintaxis, como se aplican y un ejemplo para verlo en accion, asi como una tecnica para que sea cargado una sola vez.. Espero les haya resultado 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.

Anuncios
pp258

Donatión

It’s for site maintenance, thanks!

$1.50