semana09a

8
UNMSM-FISI Curso: ALGORITMICA II Prof. GASA HERENCIA MULTIPLE 1

Upload: richard-joser

Post on 25-Dec-2015

216 views

Category:

Documents


1 download

DESCRIPTION

algoritmia

TRANSCRIPT

Page 1: Semana09A

UNMSM-FISICurso: ALGORITMICA IIProf. GASA

HERENCIA MULTIPLE

1

Page 2: Semana09A

/***************************************** Author: GASA S09HMultiple01 Version Mayo 2005 Este es un ejemplo muy sencillo en el que una clase, Der, hereda de otras os clases Base1, Base2. En este programa no hay complicaciones. En la herencia múltiple las reglas de inicio de los miembros son una extensión de los vistos en la herencia simple. De igual forma, los mecanismos de herencia de los miembros están gobernados por las declaraciones de private, protected y public en las clases. El orden en el que se especifican las clases bases en la lista de herencia sólo afecta al orden en que se van a invocar los constructores, y destructores de las clases base desde los constructores y destructores de la clase derivada. No está permitido que una misma clase base aparezca más de una vez en la lista de herencia, esto es, que sea una clase base directa más de una vez para una clase derivada. Sin embargo, pueden aparecer múltiples ocurrencias de la clase base de forma indirecta, a través de otra clase base directa.******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>

class Base1 { protected: int b1; public: void Inicia_B1(int v) { b1=v; }};class Base2 { protected: int b2; public: void Inicia_B2(int v) { b2=v; } int Ret (void) { return b2; }};class Der: public Base1, public Base2 { public: void print (void) {cout << "b1= " << b1 << "\tb2= " << Ret() << "\n"; }};void main (void){ Der d; d.Inicia_B2(78); d.Inicia_B1(34); d.print(); // Saca b1=34 b2=78

system("PAUSE"); return(0);}

/***************************************** Author: GASA S09HMultiple02 Version Mayo 2005 Vamos a ver a continuación otro ejemplo de herencia múltiple, en el que las clases tienen constructores. De todo lo anterior se deduce que las clases bases se construyen en el orden en que aparecen en la declaración de C (class C: public A, public B, por lo que en nuestro ejemplo primero A y luego B). Una vez que las clases han recibido los valores iniciales, se ejecuta el constructor de la clase derivada. Mientras que ninguna de las clases base tenga constructor, o que todas las clases bases tengan un constructor por defecto, la clase derivada no tiene porque tener constructor. De todas formas es una buena práctica de programación que todas las clases tengan un constructor para de esta forma contar con un mecanismo que permita pasar argumentos a los constructores de sus clases bases. En cuanto a los destructores, decir que al igual que en la herencia simple, se llaman en orden inverso a la derivación.******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>

class A { protected: int a; public: A (int valor) { cout << "Constructor de A\n"; a=valor; } ~A () { cout << "Destructor de A\n"; }};

class B { protected: int b; public: B (int valor) { cout << "Constructor de B\n"; b=valor; } ~B () { cout << "Destructor de B\n"; }};

// C hereda de A y de Bclass C: public A, public B {

2

Page 3: Semana09A

public: C(int v1, int v2) : B(v2), A(v1) { cout << "Constructor de C\n"; } ~C () { cout << "Destructor de C\n"; } int operar (void) { return a*a+b*b; }};

int main (void){ C obj(4, 5); cout << obj.operar() << "\n";

system("PAUSE"); return(0);};

/***************************************** Author: S09HMAmbig03 Version Mayo 2005 Supóngase que se modifica el programa S09HMultiple01 de la siguiente forma:******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>

class Base1 { protected: int b1; public: void Inicia(int v) { b1=v; }};

class Base2 { protected: int b2; public: void Inicia(int v) { b2=v; } int Obtener (void) { return b2; }};

class Der: public Base1, public Base2 { public: void Mostrar (void) { cout << "b1= " << b1 << "\tb2= " << Obtener() << "\n"; }};

int main (void) { Der d;

//d.Inicia(78); // Ambigüedad. No puede hacerse asi, sino como el siguiente d.Base1::Inicia(78); d.Base2::Inicia(34); d.Mostrar();

system("PAUSE"); return(0);}

/***************************************** Author: GASA S09HMAmbig031 Version Mayo 2005 En este ejemplo, se solucionan las ambiguedades usando el operador de ambito ******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>

class A { protected: int i;};class B: public A {};class C: public A {};class D: public B, public C { public: //int Retorna (void) { return i;} //Da error, no funciona int Retorna (void) {return C::i;}//Asi si, Ok};int main (void){ D d1; int j; j=d1.Retorna();

system("PAUSE"); return(0);}

/***************************************** Author: S09HMAmbig032 VersionMayo 2005 Herencia Multiple, Ambigüedades La clase GerenteVentas contiene de forma indirecta a la calse Empleado dos veces, una a traves de la clase Vendedor y otra de la clase Gerente. ******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>

3

Page 4: Semana09A

#include <conio.h>#include <string.h>

class Empleado { protected: char nombre[30]; public: Empleado(); Empleado(char *nom); char *Nombre() const;};

class EmpleadoHoras: public Empleado { protected: float horas; float salario; public: EmpleadoHoras ():Empleado() {}; EmpleadoHoras (char *nom); void FijaSalario (float s); void FijaHoras (float h); void SacaNombre (void) const;};

class Gerente: public Empleado { float salario_semanal; public: Gerente ():Empleado() {}; Gerente (char *nom); void FijaSueldo (float s);};

class Vendedor: public EmpleadoHoras { float comision; float ventas; public: Vendedor ():EmpleadoHoras() {}; Vendedor (char *nom); void FijaComision (float c); void FijaVentas (float v); void SacaComision (void);};//la clase GerenteVentas contiene de forma indirecta a la clase Empleado dos //veces, una a través de Vendedor y otra a través de Gerente.class GerenteVentas: public Vendedor, public Gerente { public: GerenteVentas(char *nom):Vendedor(nom), Gerente(nom) {};};

// Funciones miembro de la clase EmpleadoEmpleado::Empleado () {

memset (nombre, ' ', 30);}Empleado::Empleado(char *nom) { strncpy (nombre, nom, 30);}char *Empleado::Nombre() const { return (char *)nombre;}// Funciones miembro de la clase EmpleadoHorasEmpleadoHoras::EmpleadoHoras (char *nom):Empleado(nom) { horas=0.0; salario=0.0;}void EmpleadoHoras::FijaSalario (float s) { salario=s;}void EmpleadoHoras::FijaHoras (float h) { horas=h;}void EmpleadoHoras::SacaNombre (void) const { cout << "El nombre del trabajador es: " << nombre << "\n";}

// Funciones miembro de la clase GerenteGerente::Gerente (char *nom):Empleado(nom) { salario_semanal=0.0;}void Gerente::FijaSueldo (float s) { salario_semanal=s;}

// Funciones miembro de la clase VendedorVendedor::Vendedor (char *nom):EmpleadoHoras(nom) { comision=0.0; ventas=0.0;}void Vendedor::FijaComision (float c) { comision=c;}void Vendedor::FijaVentas (float v) { ventas=v;}void Vendedor::SacaComision (void) { cout << comision << "\n";}int main(void){

4

Page 5: Semana09A

//Se puede emplear un puntero a una clase base Empleado *ApE; EmpleadoHoras A1("Juan Marco PORTESA"); Gerente G1("Alberto FUGIMITO"); Vendedor V1("Ana Helena GINO"); //para apuntar a cualquier instancia de una clase derivada. ApE=&A1; // ¿...? cout << ApE->Nombre() << "\n"; // Muestra Juan Marco PORTESA ApE=&G1; cout << ApE->Nombre() << "\n"; // Muestra Alberto FUGIMITO ApE=&V1; cout << ApE->Nombre() << "\n\n"; // Muestra Ana Elena GINO //------------------------- GerenteVentas gv("Marcelinovski PETROSIAN"); //cout << gv.Nombre() << "\n"; // Error. Con esto no funciona, es ambiguo cout << gv.Gerente::Nombre() << "\n"; // Con esto sí. //cout << gv.Vendedor::Nombre() << "\n"; // Esto es equivalente al anterior ¿Porqué? system("PAUSE"); return(0);}

/***************************************** Author: S09HMAmbig033 VersionMayo 2005 Herencia Multiple, Ambigüedades******************************************/#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <conio.h>#include <string.h>

class Empleado { protected: char nombre[30]; public: Empleado(); Empleado(char *nom); char *Nombre() const;};

class EmpleadoHoras: public Empleado { protected: float horas; float salario; public: EmpleadoHoras ():Empleado() {}; EmpleadoHoras (char *nom); void FijaSalario (float s);

void FijaHoras (float h); void SacaNombre (void) const;};

class Gerente: public Empleado { float salario_semanal; public: Gerente ():Empleado() {}; Gerente (char *nom); void FijaSueldo (float s);};

class Vendedor: public EmpleadoHoras { float comision; float ventas; public: Vendedor ():EmpleadoHoras() {}; Vendedor (char *nom); void FijaComision (float c); void FijaVentas (float v); void SacaComision (void);};//la clase GerenteVentas contiene de forma indirecta a la clase Empleado dos //veces, una a través de Vendedor y otra a través de Gerente.class GerenteVentas: public Vendedor, public Gerente { public: GerenteVentas(char *nom):Vendedor(nom), Gerente(nom) {};};

// Funciones miembro de la clase EmpleadoEmpleado::Empleado () { memset (nombre, ' ', 30);}Empleado::Empleado(char *nom) { strncpy (nombre, nom, 30);}char *Empleado::Nombre() const { return (char *)nombre;}// Funciones miembro de la clase EmpleadoHorasEmpleadoHoras::EmpleadoHoras (char *nom):Empleado(nom) { horas=0.0; salario=0.0;}void EmpleadoHoras::FijaSalario (float s) { salario=s;}void EmpleadoHoras::FijaHoras (float h) { horas=h;

5

Page 6: Semana09A

}void EmpleadoHoras::SacaNombre (void) const { cout << "El nombre del trabajador es: " << nombre << "\n";}

// Funciones miembro de la clase GerenteGerente::Gerente (char *nom):Empleado(nom) { salario_semanal=0.0;}void Gerente::FijaSueldo (float s) { salario_semanal=s;}

// Funciones miembro de la clase VendedorVendedor::Vendedor (char *nom): EmpleadoHoras(nom) { comision=0.0; ventas=0.0;}void Vendedor::FijaComision (float c) { comision=c;}void Vendedor::FijaVentas (float v) { ventas=v;}void Vendedor::SacaComision (void) { cout << comision << "\n";}int main(void){ //Se puede emplear un puntero a una clase base Empleado *ApE; EmpleadoHoras A1("Juan Marco PORTESA"); Gerente G1("Alberto FUGIMITO"); Vendedor V1("Ana Helena GINO"); //para apuntar a cualquier instancia de una clase derivada. ApE=&A1; // ¿...? cout << ApE->Nombre() << "\n"; // Muestra Juan Marco PORTESA ApE=&G1; cout << ApE->Nombre() << "\n"; // Muestra Alberto FUGIMITO ApE=&V1; cout << ApE->Nombre() << "\n\n"; // Muestra Ana Elena GINO

//----------------------------------------------------- /* Si una clase actúa como clase base de forma indirecta más de una vez, * habrá ambigüedad cuando se produzcan conversiones entre la clase base y la

* clase derivada. Si se tiene el siguiente fragmento de código en la función principal * de nuevo existe ambigüedad. Para solucionarlo debemos recurrir a un casting. */ Empleado *ptr_emp; GerenteVentas *ptr_gv, gv("PEPE"); ptr_gv=&gv; //ptr_emp=ptr_gv; // ambiguous conversions from 'class GerenteVentas *' to 'class Empleado *' ptr_emp=(Gerente *)ptr_gv;// Con esto si funciona cout << ptr_emp->Nombre() << "\n"; system("PAUSE"); return(0);}

Problemas Propuestos:1. Implemente la siguiente herencia simple

2. Implemente la siguiente jerarquía de clases

FiguraCuadrado

Circulo

Vehículo

Auto Camión

Furgoneta

6