martes, 10 de enero de 2017

Capítulo 14. Herencia multiple

La herencia multiple Una de las oportunidades que nos ofrece el lenguaje c++ es la posibilidad de que un objeto tenga la herencia de mas de una clase; esta ventaja fue considerada por los desarrolladores de Java como una pega y la quitaron, e incluso hay desarrolladores de c++ que prefieren evitar este tipo de herencia ya que puede complicar mucho la depuracion de programas Para ilustrar un caso de herencia multiple hemos definido la superclase Habitante; de ella heredan dos clases distintas: Humano (que hablan) y Animal (que matan). Ahora queremos definir un ente que tiene propiedades de esas dos clases: Militar, ya que el militar habla y ademas mata. Como podemos definirlo? con una herencia multiple. Vamos la definicion de la superclase o clase padre Habitante Notas de la logia POO Conviene definir todos los metodos de un clase como const siempre que en el metodo no se modifiquen los atributos. Tu resistencia es inutil. unete a nosotros o muere. Definir metodos como const le facilitara el trabajo al compilador y al programador. Nota el codigo necesita revision y testeo /** * Habitante.hpp * Clase que define el objeto habitante * * Pello Xabier Altadill Izura * */ using namespace std; #include class Habitante { private: char *nombre; int edad; public: Habitante(); virtual ~Habitante(); Habitante(const Habitante &); virtual void dormir(); // setter/getter o accessors virtual char *getNombre() const { return this->nombre;} // inline virtual void setNombre(char *nombre) { this->nombre = nombre; } // inline virtual int getEdad() const { return this->edad;} // inline virtual void setEdad(int edad) { this->edad = edad; } // inline }; Y su implementacion /** * Habitante.cpp 69 Capítulo 14. Herencia multiple * Programa que implementa la clase habitante * * Pello Xabier Altadill Izura * Compilacion: g++ -c Habitante.cpp * */ #include "Habitante.hpp" // Constructor Habitante::Habitante() { cout << "-clase habitante- Habitante construido."<< endl; } // Destructor Habitante::~Habitante() { cout << "-clase habitante- Habitante "<< this->getNombre() << " destruido."<< endl; } // constructor copia Habitante::Habitante(const Habitante & original) { nombre = new char; original.getNombre(); } // metodo dormir void Habitante::dormir() { cout << "-clase habitante- zzzzzZZZZzzzzz zzz" << endl; } Humano La clase Humano, que hereda de Habitante /** * Humano.hpp * Clase que define el objeto humano * * Pello Xabier Altadill Izura * */ #include "Habitante.hpp" // hereda atributos y metodos de la superclase Habitante class Humano : public Habitante { private: char *idioma; public: Humano(); virtual ~Humano(); 70 Capítulo 14. Herencia multiple Humano(const Humano &); virtual void hablar(char *bla) const; // setter/getter o accessors virtual char *getIdioma() const { return this->idioma;} // inline virtual void setIdioma(char *idioma) { this->idioma = idioma; } // inline }; Y su implementacion /** * Humano.cpp * Fichero que implementa el objeto humano * * Pello Xabier Altadill Izura * */ #include "Habitante.hpp" // Constructor Humano::Humano() { cout << "-clase Humano- Humano construido."<< endl; } // Destructor Humano::~Humano() { cout << "-clase Humano- Humano "<< this->getNombre() << " destruido."<< endl; } // constructor copia Humano::Humano(const Humano & original) { idioma = new char; idioma = original.getIdioma(); } // metodo hablar void Humano::hablar(char *bla) const { cout << "-clase Humano-" << this->getNombre() << " dice: " << bla << endl; } Animal La clase Animal, que hereda de Habitante /** * Animal.hpp * Clase que define el objeto Animal * * Pello Xabier Altadill Izura * */ #include "Habitante.hpp" 71 Capítulo 14. Herencia multiple // hereda atributos y metodos de la superclase Habitante class Animal : public Habitante { private: int patas; public: Animal(); virtual ~Animal(); Animal(const Animal &); virtual void matar() const; // setter/getter o accessors virtual int getPatas() const { return this->patas;} // inline virtual void setPatas(int patas) { this->patas = patas; } // inline }; Y su implementacion /** * Animal.cpp * Programa que implementa la clase Animal * * Pello Xabier Altadill Izura * Compilacion: g++ -c Animal.cpp * */ #include "Animal.hpp" // Constructor Animal::Animal() { cout << "-clase Animal- Animal construido."<< endl; } // Destructor Animal::~Animal() { cout << "-clase Animal- Animal "<< this->getNombre() << " destruido."<< endl; } // constructor copia Animal::Animal(const Animal & original) {} // metodo matar void Animal::matar() const { cout << "-clase Animal-" << this->getNombre() << " Matar! Matar! Matar! " << endl; } 72 Capítulo 14. Herencia multiple La herencia multiple! Aqui esta la clase Militar, que hereda de Humano y Animal. /** * Militar.hpp * Clase que define el objeto Militar * * Pello Xabier Altadill Izura * */ // Herencia multiple de Humano y Animal class Militar : public Animal { //, public Humano { private: char *rango; 73 Capítulo 14. Herencia multiple public: Militar(); ~Militar(); Militar(const Militar &); // sobrescribe metodos void matar() const; void hablar(char *bla) const; // un metodo poco probable entre cualquier uniformado... void razonar() const; // setter/getter o accessors char *getRango() const { return this->rango;} void setRango(char *rango) { this->rango = rango;} }; Y su implementacion /** * Militar.cpp * Programa que implementa la clase Militar * * Pello Xabier Altadill Izura * Compilacion: g++ -c Habitante.cpp * g++ -c Humano.cpp * g++ -c Animal.cpp * g++ Militar.cpp Habitante.o Humano.o Animal.o -o Militar */ #include "Militar.hpp" // Constructor Militar::Militar() { cout << "-clase Militar- Militar construido."<< endl; } // Destructor Militar::~Militar() { cout << "-clase Militar- Militar "<< this->getNombre() << " destruido."<< endl; } // constructor copia Militar::Militar(const Militar & original) { cout << "-clase Militar- Militar copia creada."<< endl; } // metodo razonar void Militar::razonar() const { 74 Capítulo 14. Herencia multiple cout << "-clase Militar-" << this->getNombre() << " Error: OVERFLOW " << endl; } // metodo hablar void Militar::hablar(char *bla) const { cout << "-clase Militar-" << this->getRango() << " " << this->getNombre() << " dice: "; cout << bla << endl; } // metodo matar void Militar::matar() const { cout << "-clase Militar-" << this->getRango() << " Matar! " << endl; cout << "-clase Militar- Somos... agresores por la paz " << endl; } // Aqui haremos multiples pruebas... int main () { return 0; } 75 Capítulo 14. Herencia multiple 76 Capítulo 15. Miembros estaticos Quereis ver un miembro no estatico? (< !-- nota docbook: quitar chorradas antes de publicar -->) Variables/Funciones estaticas Dentro de las clases podemos definir atributos y metodos estaticos. Tienen de particular que son accesibles sin necesidad de definir una clase y que su valor es EL MISMO en todas los objetos que se vayan creando de una clase. Es como una variable global de una clase. Con este ejemplo se ve su uso, y de paso se revisa el tema de punteros a funciones. (si, has leido bien). /** * Soldado.hpp * Clase que define el objeto soldado muestra el uso de variables estaticas * y metodos estaticos. Todo lo estatico escapa del ambito de la clase y puede * ser invocado desde el exterior * * Pello Xabier Altadill Izura * */ using namespace std; #include class Soldado { public: // constructores Soldado(); Soldado(char *nombre, int unidad); // destructor ~Soldado(); // copia Soldado(Soldado const &); // get/set char *getNombre () const { return this->nombre; } void setNombre (char *nombre) { this->nombre = nombre; } int getUnidad () const { return this->unidad; } void setUnidad (int unidad) { this->unidad = unidad; } void matar() const; void darOrden (char *orden) const; // metodo que toma como parametro una funcion void ejecutaAccion ( void (*accion) (int,int)); static int TotalSoldados; // variable estatica! static int TotalBalas; // variable estatica! // Funciones estaticas static int getTotalSoldados () { return TotalSoldados; } static int getTotalBalas () { return TotalBalas; } 77 Capítulo 15. Miembros estaticos private: char *nombre; int unidad; }; Y su implementacion. Se recomienda probar y ejecutar para comprobar el funcionamiento de las variables estaticas. /** * Soldado.cpp * Programa que implementa la clase Soldado * * Pello Xabier Altadill Izura * Compilacion: g++ Soldado.cpp -o Soldado */ #include "Soldado.hpp" // Constructor Soldado::Soldado(): nombre("Ryan"), unidad(101) { TotalSoldados += 1; TotalBalas++; cout << "Soldado " << nombre << " construido. Unidad: " << unidad << endl; } // Constructor parametrizado Soldado::Soldado(char *nombre, int unidad) { TotalSoldados++; TotalBalas++; this->nombre = nombre; this->unidad = unidad; cout << "Soldado " << nombre << " :Soldado construido." << endl; } // Destructor Soldado::~Soldado() { TotalSoldados--; cout << "Soldado "<< this->getNombre() << " destruido."<< endl; } // constructor copia Soldado::Soldado(const Soldado & original) { nombre = new char; nombre = original.getNombre(); cout << "-clase Soldado- Soldado copia creada."<< endl; } // metodo matar void Soldado::matar() const { 78 Capítulo 15. Miembros estaticos TotalBalas--; cout << this->getNombre() << " Matar es lo mio " << endl; cout << "Born to kill. paz. Es por la dualidad de Kant" << endl; } // metodo darOrden void Soldado::darOrden(char *orden) const { cout << "Recluta patoso!" << endl; cout << this->getNombre() << " unidad " << this->getUnidad() << " ordena: "; cout << orden << endl; } // metodo ejecutaAccion: ejecuta la funcion que se le pasa como parametro void Soldado::ejecutaAccion ( void (*accion) (int,int)) { accion(5,7); cout << "Recluta patoso!" << endl; } // ATENCION IMPORTANTE: HAY QUE DEFINIR E INICIAR LAS VARIABLES ESTATICA SI NO // el compilador nos puede poner pegas int Soldado::TotalSoldados = 0; int Soldado::TotalBalas = 0; // Definimos una funcion ajena a la clase desde la cual accederemos // a la variable estatica, con lo que se demuestra que la variable estatica // esta fuera de la "capsula" de la clase. void recuentoSoldados(void); // definimos otra funcion esta para pasarsela como parametro a un metodo de la clase void carga (int balas, int granadas); // funcion principal // Aqui haremos multiples pruebas... int main () { int i, resp; // creamos los soldados Soldado peloton[10]; Soldado Hanks = Soldado("Hanks",105); // definicion de puntero de funcion: void (*funcion) (int, int) = carga; // Si hay mas de una funcion carga sera la que tenga los mismos parametros // y el mismo tipo de retorno // llamamos a la funcion recuento recuentoSoldados(); peloton[0].darOrden("Todos en formacion."); peloton[2].darOrden("Canta el colacao!"); // recorremos los 10 soldados y hacemos algo dependiendo de la entrada // Si matamos unos cuantos modificaremos la variable de TotalSoldados 79 Capítulo 15. Miembros estaticos for (i = 0; i < 10 ; i++) { cout << "Elije 0 o cualquier otro numero: " << endl; cin >> resp; if (resp == 0) { // matamos al soldado peloton[i].~Soldado(); } else { peloton[i].matar(); // tiramos una bala } // Invocamos el metodo estatico? // es un acceso DIRECTO sin necesitar un objeto definido resp = Soldado::getTotalSoldados(); cout << "Cuantos quedan? " << resp << endl; }//for // accedemos directamente a variable estatica cout << "Total balas antes de recarga: " << Soldado::TotalBalas << endl; // hacemos una recarga: Hanks.ejecutaAccion(funcion); // llamamos a la funcion recuento recuentoSoldados(); return 0; } // implementacion de la funcion recuento // muestra el numero de soldados. Podemos acceder DIRECTAMENTE a la variable statica void recuentoSoldados () { cout << "Cuantos soldados quedan vivos? " << endl; cout << "En total: " << Soldado::TotalSoldados << " soldados"<< endl; cout << "Municion? " << endl; cout << "En total: " << Soldado::getTotalBalas() << " balas" << endl; } // funcion que carga municion del peloton void carga (int balas, int granadas) { cout << "Cargando balas: " << balas << endl; Soldado::TotalBalas += balas ; cout << "Cargando granadas: " << granadas << endl; } Bueno, y con esto ya son dos semanas dandole al c++ y aprendiendo su abc... 

No hay comentarios:

Publicar un comentario