Clases

Tu primera clase c++ No hay que perder de vista el hecho de que c++ es un lenguaje orientado a objetos. Sin animos de volver a explicar que es la POO, los beneficios que constituye vamos a limitarnos a resumir. Una clase c++ es la representacion de un objeto. Un objeto es una entidad formada por sus atributos y sus metodos. Con el afan de hacer las cosas ordenadamente, siempre se separa la definicion de la clase en un fichero de cabedeceras (extension .hpp, similar al .h de lenguaje c) y la implementacion se especifica en un fichero cpp. Generalmente las clases c++ tienen el mismo aspecto: se definen unos atributos y unos metodos. Entre los metodos se pueden incluir metodos constructores y la destructora. Ademas de eso se puede definir si los atributos y clases son publicas, protegidas y privadas, dependiendo del nivel de encapsulacion que le queramos dar a la clase. Veamos la representacion del objeto coche en una clase c++:


/**
* Coche.hpp
* Clase cabecera que define el objeto Coche
*
* Pello Xabier Altadill Izura
*
* No se compila.
*/

using namespace std;
#include <iostream>

class Coche {
	
public:
	
	Coche();
		
	Coche(char *m,int cil,int cab);
	
	~Coche();
	
	void arranca();
		
	void detiene();
	
	void acelera();

private:

	char *marca;

	int cilindrada;

	int caballos;

};


Y este seria el fichero de implementacion (se puede tener todo en un unico fichero)


/**
* Coche.cpp
* Fichero que implementa la cabecera de la clase Coche.
* NO HACE NADA CONCRETO solo es una muestra
*
* Pello Xabier Altadill Izura
* 
* Compilar usando: g++ -c Coche.cpp
*/

// Hay que incluir el fichero de cabecera
#include "Coche.hpp"

// Implementacion de constructor
Coche::Coche() {
	
	cout << "Coche creado." << endl;

}


// Implementacion de constructor (con SOBRECARGA)
Coche::Coche (char *m,int cil,int cab) {}
	

// Implementacion de destructor. Util para liberar memoria.
Coche::~Coche() {

	cout << "Coche destruido." << endl;

}


// implementaciones de metodos...
void Coche::arranca() {}

void Coche::detiene() {}

void Coche::acelera() {}

/**
* Podemos usar una clase main para hacer testeos con la clase
* NOTA IMPORTANTE
* Atencion : al usar esta clase en otra que ya tiene funcion
* main, no se puede tener otra main.
*/
//int main () {
//cout << "Lo hise!!\n" << endl;
//return 1;
//}


Podemos usar clases dentro de otras clases? si claro. Veamos la definicion de un Garaje.


/**
* Garaje.hpp
* Cabecera del objeto Garaje
*
* En este caso invocamos otro objeto: Coche
*
* Pello Xabier Altadill Izura
*
* La cabecera como tal no se compila
*/

using namespace std;
#include <iostream>
#include "Coche.hpp"

/*
* Definicion de clase Garaje
*/
class Garaje {

private:

	int maxCoches;

public:

	Garaje();
	
	Garaje(int maxCoches);

	~Garaje();
	
	int entra(Coche coche);

	int sale(Coche coche);

	bool estaLleno();

};


Y esta seria la implementacion:


/**
* Garaje.cpp
* Implementacion de Clase Garaje
*
* Pello Xabier Altadill Izura
* Atencion: necesitamos el archivo objeto de la clase Coche!!!
* Compilar con: g++ -c Coche.cpp
* g++ -Wall Garaje.cpp Coche.o -o Garaje
*/

#include "Garaje.hpp"

/*
* Implementacion de clase Garaje
*/

/**
* Constructor por defecto
*/
Garaje::Garaje(){

	cout << "Garaje." << endl;

	maxCoches = 3;

}


/**
* Constructor parametrizado
*/
Garaje::Garaje(int mx){
	
		maxCoches = mx;

}


/**
* Destructor 
*/ 
Garaje::~Garaje(){}


/**
* entra: un coche entra en el garaje
*/
int Garaje::entra(Coche coche) {

	cout << " Entra un coche." << endl;
	return 0;

}


/**
* sale: un objeto coche sale del garaje
*/
int Garaje::sale(Coche coche) {

	cout << " Sale un coche." << endl;
	return 0;

}

/**
* estaLleno?: devuelve booleano con la respuesta
*/
bool Garaje::estaLleno() {

	return false;

}


/**
* y aqui la funcion main para hacer nuestras pruebillas
*/
int main () {
	
	cout << " Creamos un garaje. " << endl;
	Garaje garaje = Garaje();

	// Creamos un par de Coches
	Coche cocheAzul = Coche();
	Coche cocheRojo = Coche();

	// Metemos y sacamos los coches
	garaje.entra(cocheAzul);
	garaje.entra(cocheRojo);
	garaje.sale(cocheRojo);

}


Funciones o metodos Setter/Getter Por mania o por costumbre o porque asi lo establecen los puristas mas talibanes de la POO casi nunca se deja acceder directamente a los atributos de una clase (se definen como private) y para acceder a ellos se implementan funciones set/get. Las herramientas de desarrollo suelen incluir la opcion de generar ese codigo de forma automatizada.

Figura: nunca tomes a broma a un desarrollador OO

Sin la menor intencion de alimentar la ya tradicional Yihad entre desarrolladores, mostremos un ejemplo y digamos de paso que no esta demas definir estas funciones como inline; cumplimos como profesionales pero no perdemos eficacia. El objeto PERRO

/**
* Perro.hpp
* Cabecera de la clase Perro con sus funciones get/set para el atributo edad
*
* Pello Xabier Altadill Izura
*
*/

using namespace std;
#include <iostream>

class Perro {

public:
	
	Perro (int initialAge);
	
	~Perro();
	
	int GetAge() { return itsAge;} // inline?
	
	void SetAge (int age) { itsAge = age;} // inline?
	
	void Ladra() { cout << "Guau Guau arrr...\n";} // inline?

private:

	int itsAge;

};

Y su implementacion

/**
* Perro.cpp
* Clase que implementa la clase Perro
*
* Pello Xabier Altadill Izura
*
* Compilado: g++ Perro.cpp -o Perro
*/

#include "Perro.hpp" 

Perro::Perro(int initialAge) //constructor
{

	itsAge = initialAge;

}


Perro::~Perro() //destructor
{
	cout << " objeto destruido." << endl;
}


/**
* La funcion principal, crea un perro y le hace ladrar
*/
int main() {

	bool test = false;

	Perro Canelo(5);
	
	Canelo.Ladra();
	
	cout << "Canelo es un perro cuya edad es: " ;
	cout << Canelo.GetAge() << " a&ntilde;os\n";

	Canelo.Ladra();
	
	Canelo.SetAge(7);
	
	cout << "Ahora Canelo es " ;
	cout << Canelo.GetAge() << " a&ntilde;os\n";

	return 0;

}