Herencia

La herencia Como bien se sabe la herencia no se reparte: se descuartiza. Bromas aparte, la herencia constituye una de las herramientas mas poderosas del culto OO. Si una clase hereda de la otra, lo que hereda son todos sus atributos y metodos. Ademas de heredarlos puede sobreescribirlos, tanto los constructores-destructores como los metodos convencionales. Veremos un ejemplo claro que resume lo que se puede hacer y los efectos de la herencia Por un lado vemos la clase generica vehiculo y su descendiente: el coche. La clase Vehiculo

/**
* Vehiculo.hpp
* Clase que define el objeto vehiculo
*
* Pello Xabier Altadill Izura
*
*/

using namespace std;
#include <iostream>

enum tipo_combustible { QUEROSENO, CANNABIS, GIRASOL, GASOIL, AGUA, PLUTONIO };

class Vehiculo {

protected:

	int cilindrada;
	
	tipo_combustible combustible;

	char *marca;

public:

	Vehiculo();

	Vehiculo(char *marca);
	
	Vehiculo(int cilindrada, tipo_combustible combustible, char *marca);
	
	~Vehiculo();

	Vehiculo(const Vehiculo &);

	void arrancar();
	
	void mover(int metros);

	// metodo tipo virtual, util cuando definamos PUNTEROS Y REFERENCIAS a vehiculo
	virtual void claxon() const {

		cout << "<clase vehiculo> Mec-meeec!! Que? meeec! Que de que? meec!" << endl;

	}


	char *getMarca() const {return this->marca;}

	tipo_combustible getCombustible() const {return this->combustible;}
	
	int getCilindrada() const {return this->cilindrada;}
	
};

Y su implementacion...

/**
* Vehiculo.cpp
* Fichero que implementa la clase vehiculo
*
* Pello Xabier Altadill Izura
*
* Compilacion: g++ -c Vehiculo.cpp
*/

#include "Vehiculo.hpp"

// Constructor
Vehiculo::Vehiculo() {

	cout << "<clase vehiculo> Vehiculo creado" << endl;

}


// Constructor
Vehiculo::Vehiculo(char *marca) {
	
	this->marca = marca;
	cout << "<clase vehiculo> Vehiculo creado con parametro marca: " << marca << endl;
	
}


// Constructor con valores iniciados
Vehiculo::Vehiculo(int cilindrada, tipo_combustible combustible, char *marca) :
	cilindrada(cilindrada),
	combustible(combustible),
	marca(marca)
{

	cout << "<clase vehiculo> Vehiculo creado con valores: " << endl;
	cout << "<clase vehiculo> cilindrada: " << cilindrada << endl;
	cout << "<clase vehiculo> combustible: " << combustible << endl;
	cout << "<clase vehiculo> marca: " << marca << endl;

}


// Destructor 
Vehiculo::~Vehiculo() {
	
	cout << "<clase vehiculo> Vehiculo destruido" << endl;

}


// Constructor copia de vehiculo
Vehiculo::Vehiculo(const Vehiculo & vehiculoOrigen) {}


// Arrancamos el vehiculo
void Vehiculo::arrancar() {
	
	cout << "<clase vehiculo> arrancando vehiculo. Brruum!!" << endl;
	
}


// Movemos el vehiculo unos metros
void Vehiculo::mover(int metros) {
	
	cout << "<clase vehiculo> moviendo vehiculo " << metros << " metros" << endl;

}

El coche, herencia de Vehiculo

/**
* Coche.hpp
* Clase que define el objeto Coche, hijo de vehiculo, se&ntilde;or del capitalismo
*
* Pello Xabier Altadill Izura
*
*/

#include "Vehiculo.hpp"

class Coche : public Vehiculo {

protected:

	int caballos;

	char *motor;

public:

	// Atencion: constructor pasando parametros por defecto estilo guru
	// pero invocando a su clase padre
	Coche():Vehiculo("Audi") {
	
		cout << "<clase coche> Coche destruido invocando al constructor vehiculo" << endl;

	}


	// Constructor que sobreescribe al de vehiculo!
	Coche(char *marca);

	// Constructor
	Coche(int cilindrada, tipo_combustible combustible, char *marca);
	
	
	// Constructor
	Coche(int caballos, char *motor) {

		this->caballos = caballos;
		this->motor = motor;
		cout << "<clase coche> Coche construido con caballos y motor" << endl;
		
	}


	// Destructor
	~Coche();
	
	// Constructor copia
	Coche(const Coche &);

	// Metodo sobreescrito
	void arrancar();
	
	// metodo que sobreescribe al virtual
	void claxon() const;

	// getter/setter
	int getCaballos() const {return this->caballos;} // inline

	char *getMotor() const {return this->motor;} // inline 

};

Y su implementacion

/**
* Coche.cpp
* Fichero que implementa la clase Coche
*
* Pello Xabier Altadill Izura
*
* Compilacion: g++ -c Vehiculo.cpp
* g++ Coche.cpp Vehiculo.o -o Coche
*/

#include "Coche.hpp"

// Constructor de coche que sobreescribe
Coche::Coche(char *marca) {

	cout << "<clase coche> Coche construido con marca: " << 
	marca << endl;

}


// Constructor de coche
Coche::Coche(int cilindrada, tipo_combustible combustible, char *marca) {

	cout << "<clase coche> Coche construido con parametros" << endl;

}


// Destructor de coche 
Coche::~Coche() {
	
	cout << "<clase coche> Coche destruido" << endl;

}


// Constructor copia de Coche 
Coche::Coche(const Coche & cocheOriginal) {
	
	marca = new char;
	marca = cocheOriginal.getMarca();
	cout << "<clase coche> Copia de coche" << endl;

}


// metodo sobreescrito
void Coche::arrancar () {
	
		cout << "<clase coche> BOOM! pam! pam! pret pret pret... pam! pret pret" << endl;

}


// metodo que sobreescribe al virtual
void Coche::claxon() const {

	cout << "<clase coche> MOOOOOC!! Mecagon tus muelas MOC-MOOOC!!" << endl;

} 


// Funcion principal
int main () {
	
	// Creamos varios coches. Veremos que al ser objetos heredados
	// se invocaran los constructores, copias, y destructores de la clase
	// padre Vehiculo
	Coche mibuga = Coche();
	Coche tucarro = Coche(mibuga);

	// probando constructor sobrescrito: se invocan los dos!
	Coche tequi = Coche("Alfalfa Romero");
	
	// podemos invocar los metodos del padre y usar sus atributos
	cout << "La marca de mi buga es: " << mibuga.getMarca() << endl;

	mibuga.arrancar();

	// Invocando metodo sobreescrito: solo se invoca el del coche.
	tucarro.arrancar();
	
	// Y si queremos invocar el metodo del padre??
	tequi.Vehiculo::arrancar();
	
	// Creamos otro vehiculo con puntero a un COCHE
	Vehiculo *vehiculo = new Coche("LanborJini");

	// Esto invocara el metodo de vehiculo, el de la clase PADRE
	vehiculo->arrancar();
	vehiculo->mover(3);
	
	// Ahora queremos invocar el claxon, pero a cual de los metodos
	// se invocara, al del Coche o al de la clase vehiculo? al haber
	// definido el metodo claxon como virtual, se invocara el metodo correcto
	// que es el del coche (vehiculo es un puntero a coche).
	vehiculo->claxon();

	return 0;

}

OUTPUT La salida de la ejecucion de Coche.cpp seria:

<clase vehiculo> Vehiculo creado con parametro marca: Audi
<clase coche> Coche destruido invocando al constructor vehiculo
<clase vehiculo> Vehiculo creado
<clase coche> Copia de coche
<clase vehiculo> Vehiculo creado
<clase coche> Coche construido con marca: Alfalfa Romero 
La marca de mi buga es: Audi
<clase coche> BOOM! pam! pam! pret pret pret... pam! pret pret
<clase coche> BOOM! pam! pam! pret pret pret... pam! pret pret
<clase vehiculo> arrancando vehiculo. Brruum!!
<clase vehiculo> Vehiculo creado
<clase coche> Coche construido con marca: LanborJini
<clase vehiculo> arrancando vehiculo. Brruum!!
<clase vehiculo> moviendo vehiculo 3 metros
<clase coche> MOOOOOC!! Mecagon tus muelas MOC-MOOOC!!