martes, 24 de julio de 2018

C++ Funciones Friend


Funciones y clases Friend.

Por lo general, un miembro privado de una clase no puede ser accedido desde fuera de esa clase, sin embargo si una función que se encuentre fuera de la clase se declara como su amiga, entonces tiene permiso para acceder a los miembros de la clase.
El uso de funciones amigas se usa comúnmente cuando no se puede usar una función miembro para ciertas operaciones.
Para declarar una función amiga de una clase, se debe anteponer la palabra clave friend al prototipo de la función en la definición de la clase. Esta declaración puede hacerse en cualquier parte de la clase, pero por convención, se hace al principio. Para hacer su miembro accesible, la clase tiene que declarar la función como una amiga en su definición, no se puede ser amiga de una clase, sin que la clase entregue su amistad a la función.
Ejemplo:

#include<iostream>
using std::cout;
using std::endl;

class Amiga{

friend void modificar(Amiga &);

public:

  Amiga():
    x(0){}

  void imprimir() const{
    cout << x << endl;
  }

private:
  int x;
};

En esta primera parte podemos ver que la declaración de friend, aparece primero dentro de la clase.

friend void modificar(Amiga &);

Incluso antes de las declaraciones miembro public, como se dijo antes, las declaraciones friend, pueden aparecer en cualquier parte de la clase, pero por convención, se colocan al principio.
La función friend, debe llevar como argumento un objeto del tipo de la clase a la que va a acceder, por eso es que el argumento en este caso es "Amiga", el cual lleva el nombre de la clase. Además, el acceso es por referencia, por eso es que se utiliza el operador &.
Lo siguiente que destaqué en esta clase, fue la declaración de la variable  int x. Esto es debido a que esta es la variable que será modificada por la función. En un principio, esta variable es iniciada por el constructor con un valor de cero.
Posteriormente, nos encontramos con una función individual, al estilo del lenguaje C, la cual habíamos declarado previamente. Esta función no es miembro de la clase Amiga. El trabajo de esta función es modificar el valor de la variable x, por un valor de 10.

void modificar(Amiga &c){
  c.x = 10;
}

Luego, pasamos a la función main. En esta función vamos a crear un objeto cambio, de la clase amiga.

int main(){
Amiga cambio;

Una vez creado el objeto, llamamos a la función imprimir, la cual nos mostrará el valor inicial de la variable x, en este caso cero.

cambio.imprimir();

Posteriormente, se modificará el valor de esa variable, llamando a la función modificar (recordar que es una función amiga), pasando como argumento, el objeto creado.

modificar(cambio);

Por último, se llama nuevamente a la función imprimir, para verificar el valor de la variable x. En este caso, al haber modificado la variable, su valor pasó a ser 10.

cambio.imprimir();

Al compilar y ejecutar este código, muestra el siguiente resultado:



El código completo es el siguiente:

#include<iostream>
using std::cout;
using std::endl;

class Amiga{

friend void modificar(Amiga &);

public:

  Amiga():
    x(0){}

  void imprimir() const{
    cout << x << endl;
  }

private:
  int x;
};

void modificar(Amiga &c){
  c.x = 10;
}

int main(){

Amiga cambio;
cambio.imprimir();

modificar(cambio);
cambio.imprimir();

return 0;
}

Esto es todo por ahora, espero se entienda. Saludos.

Gustavo J. Cerda Nilo, Julio 2018

lunes, 2 de julio de 2018

C++ Composición


COMPOSICIÓN

La composición, es una forma común de reutilizar software, pudiendo utilizar objetos como miembros de otras clases.  En palabras más sencillas, es como utilizar clases como si estas fuesen un tipo de variable.

Para entender un poco más la composición, debemos pensar que en nuestro mundo, muchos objetos son construidos usando objetos más pequeños. Por ejemplo un auto es ensamblado usando ruedas, motor, asientos, carrocería, entre otros.

Para el siguiente ejemplo, se utilizarán dos archivos de encabezado .h, dos archivos  con funciones .cpp y un archivo principal (main) .cpp
Para esto, vamos a crear un nuevo proyecto, que en mi caso llamaré ComposicionEjemplo.
Como en el ejemplo de construir un automóvil con partes más pequeñas, nuestro ejemplo se basará en una clase sobre un automóvil y otra con sus características, las cuales serán, por un asunto de simplicidad y no complicar el ejemplo, simplemente su marca, modelo y color.

La primera clase que escribiremos se llamará Caracteristica y la guardaremos como archivo de encabezado, con el nombre de Caracteristica.h
Esta clase llevará una función imprimir, la cual será constante. Esto es debido a que su trabajo es mostrar un mensaje el cual no tiene sentido se pueda modificar. Por lo general, las funciones imprimir o funciones get, se declaran como constantes.
Para que una función se declare como constante, debe llevar la palabra const, después de los paréntesis.

#ifndef CARACTERISTICA_H
#define CARACTERISTICA_H

#include<iostream>
using std::string;

class Caracteristica{

  public:
    Caracteristica(string);
    void imprimir()const; //funcion constante

  private:
    const string detalle;
};
#endif // CARACTERISTICA

Ahora lo que vamos a hacer es crear el archivo fuente llamado Caracteristica.cpp
En este archivo vamos a iniciar nuestra constante mediante el constructor y le agregaremos una tarea a nuestra función "imprimir". 

Como se puede ver, el constructor utiliza el inicializador de miembros para iniciar nuestra constante. Además, el constructor utiliza un argumento, el cual también es una constante.
La función imprimir, simplemente muestra en pantalla el contenido de la constante que llamamos "detalle"

#include<iostream>
using std::string;
using std::cout;
using std::endl;

#include "Caracteristica.h"

Caracteristica::Caracteristica(const string d):
  detalle(d){}

void Caracteristica::imprimir()const{
  cout << detalle << endl;
}

Nuestro siguiente archivo, es otro archivo de encabezado al cual nombré como Auto.h
En este archivo, se declaró la clase Auto. Esta clase utiliza lo que llamamos composición, ya que utiliza a la clase Caracteristica, como si se tratase de una variable.

El constructor, utiliza como argumento la clase Caracteristica. Este argumento funciona como si fuese un string, debido a recibirá un texto. Caractaristica, queda como un nuevo tipo de dato el cual utilizamos para declarar las variables marca, modelo y color.

#ifndef AUTO_H
#define AUTO_H

#include<iostream>
using std::string;

#include "Caracteristica.h"

class Auto{

  public:
    Auto(const string, Caracteristica, Caracteristica, Caracteristica);
    void imprimir()const;

  private:
    const string vehiculo;
    Caracteristica marca;
    Caracteristica modelo;
    Caracteristica color;
};

#endif // AUTO_H

El siguiente archivo, es otro código fuente, el cual llamaremos Auto.cpp
En este archivo, vamos iniciaremos las variables o constantes, mediante el uso del constructor y utilizaremos la función imprimir, para mostrar un texto por pantalla.

Como se puede ver, el constructor inicia las variables o constantes correspondientes, esta vez utilizando la composición, el cual indica que recibirá cuatro argumentos. 

En la función imprimir, utilizamos la composición para llamar a la función imprimir y que muestre por pantalla el texto que será establecido en la función main.

#include "Caracteristica.h"
#include "Auto.h"

#include<iostream>
using std::string;
using std::cout;
using std::endl;

Auto::Auto(const string v, Caracteristica mar, Caracteristica mod, Caracteristica col):
  vehiculo(v), marca(mar), modelo(mod), color(col){}

void Auto::imprimir()const{
  cout << "Tipo de vehiculo: " << vehiculo << endl;
  cout << "Marca: ";
  marca.imprimir();
  cout << "Modelo: ";
  modelo.imprimir();
  cout << "Color: ";
  color.imprimir();
  cout << endl;
}
 
Por último, creamos el archivo main.cpp
En este archivo creamos tres objetos de la clase Caracteristica; un objeto marca, otro objeto modelo y un objeto color. Estos objetos reciben un argumento de texto. 

Luego creamos un objeto vehículo, de la clase Auto. Este recibe cuatro argumentos, según declaramos en su prototipo. 

Ya por último utilizamos el objeto vehículo para llamar a la función imprimir y mostrar por pantalla los datos ingresados.

#include "Auto.h"

int main(){

  Caracteristica marca("Toyota");
  Caracteristica modelo("Yaris");
  Caracteristica color("Rojo");
  Auto vehiculo("Auto", marca, modelo, color);

  vehiculo.imprimir();

return 0;
}

El resultado es el siguiente:



En una clase anterior, cuando presentamos la envoltura del preprocesador, mencioné que al no incluirlas cuando trabajamos con la composición, podría ocasionar un error al momento de querer compilar. Esto sucede si por ejemplo, borramos la envoltura del preprocesador del archivo Caracteristica.h

Por ejemplo, en la siguiente imagen, al comentar dichas líneas, me arroja un error al querer compilar.
 




Hay que tener presente que esto de la composición, está muy ligado a la herencia y sirve para tener cada clase por separado y enfocada en realizar una tarea.

Espero se haya entendido. Saludos

Gustavo J. Cerda Nilo. Julio 2018

C++ El apuntador This

El apuntador This En C++, cada objeto tiene acceso a su propia dirección a través de un puntero o apuntador denominado This. Lo...