Clases y sus amigas

Clases dentro de Clases Una clase puede ser el atributo de otra clase. Veamos como metemos la clase soldado dentro del tanque, esta seria la cabecera:

/**
* Tanque.hpp
* Clase que define el objeto Tanque . El objeto tanque estara lleno
* de Objeto soldados, lo que nos sirve para demostrar el uso de clases
* como atributos, etc..
*
* Pello Xabier Altadill Izura
*
*/

using namespace std;
#include <iostream>

#include "Soldado.hpp"

class Tanque {

public:

	// constructores
	Tanque();

	Tanque(char *nombre, int proyectiles,Soldado soldado);

	// destructor
	~Tanque();

	// copia
	Tanque(Tanque const &);

	// get/set
	char *getNombre () const { return this->nombre; }
	
	void setNombre (char *nombre) { this->nombre = nombre; }

	int getProyectiles () const { return this->proyectiles; }

	void setProyectiles (int proyectiles) { this->proyectiles = proyectiles; }
	
	Soldado getSoldado () const { return this->soldado; }

	void setSoldado (Soldado soldado) { this->soldado = soldado; }

	void avanzar(int metros) const;
	
	void disparar();


private:

	char *nombre;

	int proyectiles;

	Soldado soldado;

};

Y su implementacion:

/**
* Tanque.cpp
* Programa que implementa la clase Tanque
* 
* Pello Xabier Altadill Izura
* Compilacion: g++ Tanque.cpp -o Tanque
*/

#include "Tanque.hpp"

// Constructor
Tanque::Tanque(): nombre("Supertanque"), 
proyectiles(10), soldado(Soldado()) {

	cout << "-clase Tanque- Tanque " << nombre << " construido. Proyectiles: " << proyectiles << endl;

}


// Constructor parametrizado
Tanque::Tanque(char *nombre, int proyectiles, Soldado soldado) {

	this->nombre = nombre;
	this->proyectiles = proyectiles;
	this->soldado = soldado;
	cout << "-clase Tanque- " << nombre << " :Tanque construido. Proyectiles: " << proyectiles << endl;

}


// Destructor
Tanque::~Tanque() {
	
	cout << "-clase Tanque- Tanque "<< this->getNombre() << " destruido."<< endl;

}


// constructor copia
Tanque::Tanque(const Tanque & original) {
	
	nombre = new char;
	nombre = original.getNombre();
	cout << "-clase Tanque- Tanque copia creada."<< endl;

}


// metodo avanzar
void Tanque::avanzar(int metros) const {

	cout << "-clase Tanque-" << this->getNombre() << " avanzando: " << metros << " m." << endl;

}


// metodo disparar
void Tanque::disparar(){
	
	if (proyectiles > 0) {

		proyectiles--;
		cout << "-clase Tanque-" << this->getNombre() << "BOOOOM!!" << endl;

	} else {
		
		cout << "-clase Tanque-" << this->getNombre() << " No queda municion." << endl;

	}

}


// funcion principal
// Aqui haremos multiples pruebas...
int main () { 

	int i, resp;
	
	// creamos los Tanques
	Tanque tanqueta = Tanque();

	// podemos sacar lso datos del soldado asi:
	cout << "El nombre del soldado es: " << (tanqueta.getSoldado()).getNombre()<< endl;

	tanqueta.avanzar(5);
	tanqueta.disparar();
	tanqueta.getSoldado().matar();

	return 0;	
}

friend: haciendo amigos Mediante la palabra reservada friend podemos declara relaciones de confianza entre clases y permitir que una clase amiga pueda acceder a los atributos y metodos privados de esa clase. Veamos el ejemplo con la Pluma y la Espada. La pluma vence a la espada pero ademas la declara como amiga porque es asi de enrollada. Veamos la declaracion de Pluma:

/**
* Pluma.hpp
* Clase que define el objeto pluma, un objeto que sirve para escribir
*
* Pello Xabier Altadill Izura
*
*/

using namespace std;
#include <iostream>

class Pluma {

public:
	
	Pluma();
	
	Pluma(char *tipo, char *usuario);
	
	~Pluma();
	
	Pluma(Pluma const &);


	// ATENCION!!! definimos la clase ESPADA como friend
	// por tanto desde ella se podra acceder a los elementos PRIVADOS de la Pluma
	friend class Espada;

	char *getTipo() const { return this->tipo;}

	char *getUsuario() const { return this->usuario;}


private:

	// metodo para escribir con la pluma
	void escribe (char *texto) {cout << "escribo con la pluma: " << texto << endl;}
	
	void test() { cout << "Mega funcion privada de Pluma!" << endl;}


	char *tipo;
	
	char *usuario;
	
};

Y su implementacion:

/**
* Pluma.cpp
* Programa que implementa la clase Pluma
*
* Pello Xabier Altadill Izura
* Compilacion: g++ -c Pluma.cpp
*/

#include "Pluma.hpp"

// Constructor
Pluma::Pluma(): tipo("tinta china"), usuario("Bertrand Russel") {

	cout << "Pluma construida." << endl;

}


// Constructor
Pluma::Pluma(char *tipo, char *usuario) {

	this->tipo = tipo;
	this->usuario = usuario;
	cout << "Pluma construida de tipo: " << tipo << endl;

}


// Destructor
Pluma::~Pluma() {
	
	cout << "Pluma destruida." << endl;

}


// Constructor copia
Pluma::Pluma(Pluma const & original) {

	tipo = new char;
	tipo = original.tipo;

}

Y ahora la declaracion de la Espada

/**
* Espada.hpp
* Clase que define el objeto Espada, un objeto que 
sirve para matar
*
* Pello Xabier Altadill Izura
*
*/


using namespace std;
#include <iostream>

class Espada {

public:
	
	Espada();
	
	Espada(char *tipo);
	
	~Espada();

	Espada(Espada const &);

	// desde este metodo accederemos a la 
	// parte privada de la pluma
	void usarPluma (char *texto); 

	char *getTipo() const { return this->tipo;}

private:

	char *tipo;

};

Y su implementacion:

/**
* Espada.cpp
* Programa que implementa la clase Espada
*
* Pello Xabier Altadill Izura
*
* Compilacion: g++ -o Espada Pluma.o Espada.cpp
*/

#include "Espada.hpp"
#include "Pluma.cpp"

// Constructor
Espada::Espada(): tipo("katana") {

	cout << "Espada construida." << endl;

}


// Constructor
Espada::Espada(char *tipo) {

	this->tipo = tipo;
	cout << "Espada construida de tipo: " << tipo << endl;

}


// Destructor
Espada::~Espada() {
	
	cout << "Espada destruida." << endl;

}


// Constructor copia
Espada::Espada(Espada const & original) {
	
	tipo = new char;
	tipo = original.tipo;

}


// metodo desde el que accedemos a Pluma
void Espada::usarPluma(char *texto) {
	
	// implementamos una pluma y...
	Pluma plumilla = Pluma();

	// y ahora accedemos a sus miembros privados: atributos ...
	cout << "La pluma es tipo: " << plumilla.tipo << endl;
	cout << "Y su usuario es: " << plumilla.usuario << endl;

	plumilla.escribe(texto);
	// e incluso a sus metodos!
	plumilla.test();

}


// funcion principal
int main () {

	int i;

	Espada tizona = Espada("mandoble");
	
	// invocamos un metodo que accedere a la zona privada de la clase
	tizona.usarPluma("jaja uso la pluma a mi antojo");

	return 0;
}

La funcion amiga Podemos declarar una funcion como amiga y nos dara acceso a TODO a traves de ese funcion. Para ilustrar esto definimos las clases Chico y Chica en un unico fichero

/**
* ChicoChica.cpp
* Clase que define el objeto Chico y Chica. Chico tiene una funcion llamada
* esNovio que dentro de chica la declaramos como friend 
y le dara acceso a todo
*
* Pello Xabier Altadill Izura
* Compilacion: g++ -o ChicoChica ChicoChica.cpp
*/

using namespace std;
#include <iostream>

class Chico {

public:

	// constructor
	Chico():nombre("Romeo") {}

	// constructor
	Chico(char *nombre) { this->nombre = nombre;}

	// destructor
	~Chico() {}


	// constructor copia
	Chico(Chico const & origen) {

		nombre = new char;
		nombre = origen.nombre;

	}


	// desde este metodo accederemos a la 
	// parte privada de la clase chica
	void esNovio(); 

	char *getNombre() const { return this->nombre;}


private:
	
	char *nombre;

};


class Chica {

public:
	
	// constructor
	Chica():
		nombre("Julieta"),
		edad(23),
		coeficienteInteligencia(140),
		medidas("95-60-95") {
		}
		

	// destructor
	~Chica() {}


	// constructor copia
	Chica(Chica const & origen) {

		nombre = new char;
		nombre = origen.nombre;

	}


	// Aqui definimos un metodo friend externo
	// que tendra acceso a toda la clase chica
	friend void Chico::esNovio(); 

	// otra opcion seria declara Chico como friend:
	// friend class Chico;


private:
	
	void pensar() { cout << "estoy pensado..." << endl; }
		
	void entrarHabitacion() { cout << "estoy entrando en la habitacion..." << endl; }
	
		
	char *nombre;
	
	int edad;
	
	int coeficienteInteligencia;
	
	char *medidas;
};


// implementacion de la funcion del chico esNovio
void Chico::esNovio() {
	
	Chica neska = Chica();

	neska.entrarHabitacion();

	cout << "Con esta funcion entro en todo! " << endl;
	cout << "Dime tu edad real chica: " << neska.edad << endl;
	cout << "Y tu coeficiente intelectual: " << 
	
	neska.coeficienteInteligencia << endl;
	cout << "joder, me parece que no te gustara el futbol." << endl;

}


// funcion principal, para las pruebas
int main () {
	
	int i;
	
	Chico mutiko = Chico();
	
	// vamos a ver si llamamos a esNovio...
	mutiko.esNovio();

	return 0;
}