Anuncios

Bienvenidos sean a este post, hoy veremos al primer pilar de OOP.

Anuncios
Anuncios

Las clases son nuestro primer elemento especial en el lenguaje porque esta nos permite crear nuevos elementos para nuestros codigos. Estos pueden ser desde una parte de codigo hasta nuevos tipos de datos. Es decir, usado correctamente ya no tendremos solamente a los tipos primitivos para crear nuestras variables, funciones, etc. Los objetos son creados a partir de las clases, estas son instancias de las clases y mediante estos podemos usar a las clases. Volviendo a estas, podemos considerarlos como moldes de los objetos y tambien podemos crear todos los que necesitemos, y cada uno sera independiente del otro. Las clases se componen de dos elementos, las propiedades que se encargan de manejar la informacion en la clase (en realidad, son variables) y los metodos se encargan de las acciones (son las funciones). Con esto comentado pasemos a ver como es su sintaxis mas basica:

class nombre_ident
{
public:
	propiedades
	metodos
private:
	propiedades
	metodos
}
Anuncios

Siempre ira la palabra class seguido del nombre identificador. En esta tendremos dos partes:

  • public, en esta iran todas las propiedades y metodos que podran ser accedidas por nuestros objetos
  • private, lo que coloquemos aca solo sera accedido por la clase y estara restringuido a los objetos creados de esta
Anuncios

Para entenderlo un poco mejor, vamos a suponer que la clase representa a un perro. Donde las propiedades de esta clase se usaran para almancenar: la edad, altura, peso, etc. y los metodos seran para las acciones como pueden ser: ladrar, caminar, comer, etc. Con esto tenemos como es una clase de forma muy basica. Para entender el concepto vamos a analizar un ejemplo y para ello crearemos un archivo con el nombre de clase.cpp y le agregaremos el siguiente codigo:

#include <iostream>

class Perro
{
public:
        int edad;
        int peso;
        int altura;
        void Ladrar() { std::cout << "Guau!!!" << std::endl; }
private:
};

int main()
{
        Perro perro;
        perro.edad = 10;
        perro.peso = 35;
        std::cout << "Edad: " << perro.edad << std::endl;
        std::cout << "Peso: " << perro.peso << std::endl;
        perro.Ladrar();
        return 0;
}
Anuncios
Anuncios

Esta no es la forma de usar una clase pero lo haremos asi por un tema de practicidad, mas adelante veremos como se debe hacer. Primero definimos a la clase donde tendremos dos partes que comentamos anteriormente. Para esta ocasion, utilizamos la parte publica donde declaramos unas propiedades y definimos un metodo para mostrar un mensaje. Por el momento, private quedara vacio. Luego en el main, primero creamos un objeto de la clase anterior y es tan simple como la declaracion de una variable, donde pasamos primero la clase seguido del nombre identificador. Luego establecemos un valor para dos propiedades de la clase y para ello primero pasamos el objetos seguido de la propiedad y unidos por el punto. Lo siguiente sera mostrar los valores de las propiedades anteriores y por ultimo ejecutaremos al metodo de la clase. Es de la misma manera que al trabajar con propiedades pero este nos devolvera las instrucciones del metodo. Compilemmos y veamos como es la salida:

$ ./clase
Edad: 10
Peso: 35
Guau!!!
$
Anuncios

Como pueden ver se realizo todo lo solicitado, volvamos a nuestro codigo y modifiquemos la clase de la siguiente manera:

class Perro
{
public:
        int edad;
        void Ladrar() { std::cout << "Guau!!!" << std::endl; }
private:
        int peso;
        int altura;
};
Anuncios

La unica modificacion que hicimos fue pasar dos propiedades (peso y altura) a la parte privada de la clase, compilemos y veamos que sucede:

$ g++ clase.cpp -o clase
clase.cpp: In function ‘int main()’:
clase.cpp:17:15: error: ‘int Perro::peso’ is private within this context
   17 |         perro.peso = 35;
      |               ^~~~
clase.cpp:9:13: note: declared private here
    9 |         int peso;
      |             ^~~~
clase.cpp:19:40: error: ‘int Perro::peso’ is private within this context
   19 |         std::cout << "Peso: " << perro.peso << std::endl;
      |                                        ^~~~
clase.cpp:9:13: note: declared private here
    9 |         int peso;
      |             ^~~~
$
Anuncios

Fallo porque como dijimos al principio, todo lo declarado o establecido en private o privado solo puede ser accedido en la clase y no desde su objeto o instancia. Pero como podemos manejar esta informacion? Para ello debemos hacer la siguiente modificacion en el codigo:

#include <iostream>

class Perro
{
public:
        int edad;
        void Ladrar() { std::cout << "Guau!!!" << std::endl; }
        void setPeso(int p) { peso = p; }
        int getPeso() { return peso; }
        void setAltura(int a) { altura = a; }
        int getAltura() { return altura; }
private:
        int peso;
        int altura;
};

int main()
{
        Perro perro;
        perro.edad = 10;
        perro.setPeso(35);
        std::cout << "Edad: " << perro.edad << std::endl;
        std::cout << "Peso: " << perro.getPeso() << std::endl;
        perro.Ladrar();
        return 0;
}
Anuncios
Anuncios

En la clase agregamos cuatro nuevos metodos. El primero de los nuevos se llama setPeso, el cual recibe un valor de tipo int y lo asigna a la propiedad peso. El siguiente metodo es para devolver el valor almacenado en peso. Los siguientes dos metodos hacen exactamente lo mismo pero para la propiedad altura. El siguiente cambio es en el main donde en lugar de usar a la propiedad peso, usamos primero al metodo setPeso para establecer el valor y luego usamos a getPeso para recuperar dicho valor. Si lo compilan y ejecutan volveremos a la primera salida. Recuerden que todo lo que ponemos en private solo puede ser accedido por la clase, los metodos en public al pertenecer a la clase, y nosotros podemos acceder desde el objeto o instancia nos permiten manipular la informacion en las propiedades privadas. Esto es una forma de control para evitar cambiar valores de forma accidental y caer en errores. Pero vamos a tener un inconveniente, para verlo vamos a modificar al main de la siguiente manera:

int main()
{
        Perro arturo;
        Perro lola;
        arturo.edad = 10;
        arturo.setPeso(35);
        lola.edad = 6;
        lola.setPeso(25);
        std::cout << "Edad Arturo: " << arturo.edad << std::endl;
        std::cout << "Peso Arturo: " << arturo.getPeso() << std::endl;
        std::cout << "Edad Lola: " << lola.edad << std::endl;
        std::cout << "Peso Lola: " << lola.getPeso() << std::endl;

        arturo.Ladrar();
        return 0;
}
Anuncios

En este codigo creamos dos objetos de la clase y establecemos para ambos objetos la propiedad edad y el peso mediante el metodo setPeso. Lo siguiente sera mostrar los datos establecidos anteriormente y solo hacemos un llamado al metodo Ladrar. Compilemos y veamos como es su salida:

$ ./clase
Edad Arturo: 10
Peso Arturo: 35
Edad Lola: 6
Peso Lola: 25
Guau!!!
$
Anuncios

Como pueden ver cada objeto tiene la misma base como es la clase pero cada uno tiene su espacio en memoria y tiene sus propios elementos. Dos elementos que tenemos de forma implicita en nuestras clases sin necesidad de definirlos o declararlos son el constructor y el destructor.

Anuncios

El constructor como su nombre lo indica es utilizado para construir nuestros objetos. Es decir, este es invocado cuando creamos el objeto y en este podemos desde establecer valores iniciales hasta llamar a metodos propios de la clase. Si no lo definimos su forma predeterminada es la siguiente:

nombre_clase() {}
Anuncios

Es simplemente un metodo con el nombre de la clase y sin ningun parametro. Como dijimos esta es la forma implicita y se genera automaticamente pero bajo ciertas circunstancias debemos definirla pero usualmente no es necesario.

Anuncios

El siguiente tema es el destructor, este se encarga de todo lo opuesto. Es decir, libera todo lo que hayamos creado en la memoria. Al igual que el constructor sino lo definimos existe de forma implicita, podemos asignarles instrucciones que ejecutara antes del final de la clase. Por ejemplo, puede cerrar la conexion a una base de datos, escribir en un archivo, modificar el valor de una variable, etc. Al igual que ocurre con el constructor tenemos una sintaxis predeterminada:

~nombre_clase() {}
Anuncios

Esta tambien se identifica con el nombre de la clase pero delante de esta llevara al signo de tilde (~) y dentro de esta podemos usar todas las instrucciones que necesitemos. Tomemos el codigo anterior y modifiquemoslo:

#include <iostream>

class Perro
{
public:
        Perro(int e, int p) {
                std::cout << "Iniciando constructor" << std::endl;
                edad = e;
                peso = p;
        }
        ~Perro() { std::cout << "Destructor invocado" << std::endl; }
        void Ladrar() { std::cout << "Guau!!!" << std::endl; }
        void setEdad(int e) { edad = e; }
        int getEdad() { return edad; }
        void setPeso(int p) { peso = p; }
        int getPeso() { return peso; }
        void setAltura(int a) { altura = a; }
        int getAltura() { return altura; }
private:
        int edad;
        int peso;
        int altura;
};

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

        arturo.Ladrar();

        return 0;
}
Anuncios
Anuncios

Lo primero que hicimos fue pasar todas las propiedades a private. En la parte public, primero agregamos un constructor. Este recibe dos argumentos, los cuales usaremos para asignarlos a la propiedad edad y peso. A su vez, en este mostramos un mensaje indicando que se inicio el constructor, es simplemente para verlo en accion y nada mas, tambien agregamos un metodo para establecer el valor de edad y recuperarlo. Tambien agregamos un destructor y en este caso solo le agregamos un mensaje para ver cuando es invocado. El resto sigue de la misma forma y con las mismas acciones. Los otros cambios los haremos en el main. El primero, es como creamos a los objetos ahora. Observen que pasamos los parametros como argumentos y no es necesario llamar a los metodos para establecerlos. Primero creamos un objeto y le establecemos los valores, para luego mostrar los valores establecidos. Volvemos a repetir los mismos pasos pero para crear otro objeto y mostrar los nuevos datos y finalmente llamar al metodo Ladrar de uno de los objetos. Compilemos y veamos que sucede:

$ ./clase
Iniciando constructor
Edad Arturo: 10
Peso Arturo: 35
Iniciando constructor
Edad Lola: 6
Peso Lola: 25
Guau!!!
Destructor invocado
Destructor invocado
$
Anuncios

Veamos lo que mas nos interesa. Cada vez que creamos un objeto nos muestra el mensaje de llamada al constructor y cuando finalizamos el programa eliminamos a los objetos y se llama al destructor, para que nos muestre los mensajes correspondientes. Todo esto es automatico como mencionamos antes. Otra posibilidad que podemos aplicar a los constructores es la sobrecarga y tener varias posibilidades para el momento de crear nuestros objetos. Otra posibilidad que podemos usar en las clases son los prototipos, tomemos el codigo anterior y hagamos la siguiente modificacion:

#include <iostream>

class Perro
{
public:
        Perro(int e, int p) {
                std::cout << "Iniciando constructor" << std::endl;
                edad = e;
                peso = p;
        }
        ~Perro() { std::cout << "Destructor invocado" << std::endl; }
        void Ladrar();
        void setEdad(int);
        int getEdad();
        void setPeso(int);
        int getPeso();
        void setAltura(int);
        int getAltura();
private:
        int edad;
        int peso;
        int altura;
};

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;
}


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

        arturo.Ladrar();

        return 0;
}
Anuncios

Este es un cambio simple en la clase. Primero cambiamos todas las definiciones de la clase por prototipos. y lo siguiente es definir cada uno de los prototipos. Si observan son las mismas instrucciones que teniamos antes pero con una sutil diferencia, tomemos una de las definiciones y analicemosla:

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

Observen que agregamos una pequeña modificacion, esta es el nombre de la clase antes de cada metodo y lo unimos mediante el operador de resolucion de ambito. Esta forma de definirlo es para indicarle cual es el destino que definimos. En este caso, le decimos que definimos al metodo setEdad en la ubicacion Perro que es nuestra clase. Si no se especifica, estos quedaran definidos como simples funciones y al compilarlo tendremos un error porque queremos usar metodos que no poseen definicion. Si lo compilan y ejecutan volveran obtener la misma salida que antes pero esto es la antesala de un tema que veremos en el proximo post.

Anuncios

En resumen, hoy hemos visto clases y objetos, que es una clase, como se compone, para que sirve, tambien vimos que es un objeto, de donde proviene, que posibilidad nos brinda, luego vimos varios ejemplos donde explicamos distintos temas relacionados a ambos. 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

Donatión

It’s for site maintenance, thanks!

$1.50