Sei sulla pagina 1di 11

Programación II Curso: 2016-2017

Tema I: Relaciones entre clases.


CP # 7: Herencia y Polimorfismo.

Objetivos:
Lograr que los estudiantes:
1. Apliquen el concepto del polimorfismo en la solución de problemas.
2. Desarrollen habilidades en la definición e implementación de clases donde se
haga uso del contenido relacionado con la herencia y el polimorfismo.

Sumario:
 Resolución de ejercicios.
o Identificación de la relación es-un entre clases.
o Implementación del polimorfismo en C++.

Introducción

En la conferencia se introdujo el concepto de polimorfismo, como una de las herramientas


fundamentales de la POO, y se demostró su estrecha vinculación con la herencia. Además,
se ejemplificó la implementación del polimorfismo en el lenguaje C++.

En la clase de hoy continuaremos profundizando en estos aspectos, trabajando en la


identificación de clases que intervienen en la jerarquía de herencia y en la necesidad del uso
del polimorfismo para una mejor solución.

Desarrollo

Ejercicio # 1

Se quiere elaborar un programa que permita representar figuras geométricas


bidimensionales, específicamente círculos, rectángulos y triángulos. De cada figura se
conoce un punto (x, y: valores reales) de referencia. En el caso de los círculos se conoce
además el radio (valor real); de los rectángulos se conoce también otro punto y en el caso de
los triángulos se conocen además los otros dos puntos (vértices). Consideraciones:

 La clase abstracta más general CFigura expresará lo común a cualquier figura.


 De cada figura se debe calcular su perímetro y su área.
 Implementar una clase CEditorFigura que permita manejar figuras geométricas en el
plano.

Nota: Elabore un programa manipulador que pruebe la jerarquía de clases implementada.

Variante de solución:

1
Figura 1. Diagrama de clases de la variante de solución.

 Archivo CPunto.h

#ifndef CPuntoH
#define CPuntoH
#include <math.h>
#include <string.h>

class CPunto
{ private:
float y;
float x;
char desc[50]; // para devolver la descripción del punto en texto
public:
CPunto(float = 0.0, float = 0.0);
float GetX(); void SetX(float);
float GetY(); void SetY(float);
float DistanciaHasta(CPunto);
char * Texto();
};

char * conv(float); // funcion agregada para convertir float a texto (char *)

#endif

 Archivo CPunto.cpp

2
#include "CPunto.h"
#include <stdlib.h>

CPunto::CPunto(float valorX, float valorY)


{
x = valorX;
y = valorY;
}

float CPunto::GetX() { return x; }


void CPunto::SetX(float valorX) { x = valorX; }
float CPunto::GetY() { return y; }
void CPunto::SetY(float valorY) { y = valorY; }

float CPunto::DistanciaHasta(CPunto p2)


{
return sqrt(pow(this->x - p2.x, 2) + pow(this->y - p2.y, 2));
}

char * CPunto::Texto()
{
strcpy(desc, "("); strcat(desc, conv(x));
strcat(desc, ", "); strcat(desc, conv(y));
strcat(desc, ")");
return desc;
}

char * conv(float x)
{
char * str = "000000000000000.00";
int dec, sign, ndig = 2; // conversion de float a cadena
char * conv = fcvt(x, ndig, &dec, &sign);
// procedimiento para añadir el punto decimal donde corresponde
for (int i = 0; i < dec; i++) str[i] = conv[i]; // parte entera
for (int i = 0; i < ndig; i++) str[dec+i+1] = conv[dec+i]; // decimales
str[dec] = '.'; str[dec+ndig+1] = 0; // coloco punto y fin de cadena
return str;
}

 Archivo CFigura.h

#ifndef CFiguraH
#define CFiguraH
#include "CPunto.h"

class CFigura // Clase abstracta


{
protected:
CPunto punto;
char desc[200];
public:
CFigura(float, float);
virtual ~CFigura();
virtual float Perimetro() = 0;
virtual float Area() = 0;
virtual char * Descripcion() = 0;
};

3
#endif

 Archivo CFigura.cpp

#include "CFigura.h"

CFigura::CFigura(float X, float Y): punto(X, Y) { }

CFigura::~CFigura() { }

 Archivo CCirculo.h

#ifndef CCirculoH
#define CCirculoH
#include "CFigura.h"
#define PI 3.14159

/* TIP PARA PREVENIR ERRORES:


Si una clase tiene funciones virtual, proporcione un destructor virtual
aunque no se requiera uno para la clase. Esto asegura que se invoque a un
destructor personalizado de la clase derivada (si hay uno) cuando un objeto
de la clase derivada se destruya mediante un apuntador de la clase base.*/

class CCirculo : public CFigura


{
protected:
float radio;
public:
CCirculo(float, float, float);
virtual ~CCirculo();
void SetRadio(float);
float GetDiametro();
virtual float Perimetro();
virtual float Area();
virtual char * Descripcion();
};
#endif

 Archivo CCirculo.cpp

#include "CCirculo.h"

CCirculo::CCirculo(float valorX, float valorY, float valorRadio)


: CFigura(valorX, valorY)
{
SetRadio(valorRadio);
}

CCirculo::~CCirculo() { }

void CCirculo::SetRadio(float valorRadio) {


radio = valorRadio > 0 ? valorRadio : 0.0;
}
float CCirculo::GetDiametro() { return 2 * radio; }
float CCirculo::Perimetro() { return PI * GetDiametro(); }
float CCirculo::Area() { return PI * radio * radio; }
char * CCirculo::Descripcion()

4
{
strcpy(desc, "\n Centro: "); strcat(desc, punto.Texto());
strcat(desc, "\n Radio: "); strcat(desc, conv(radio));
return desc;
}

 Archivo CRectangulo.h

#ifndef CRectanguloH
#define CRectanguloH
#include "CFigura.h"

class CRectangulo : public CFigura


{
protected:
CPunto punto2;
public:
CRectangulo(float, float, float, float);
virtual ~CRectangulo();
virtual float Perimetro();
virtual float Area();
virtual char * Descripcion();
};
#endif

 Archivo CRectangulo.cpp

#include "CRectangulo.h"

CRectangulo::CRectangulo(float X1, float Y1, float X2, float Y2)


: CFigura(X1, Y1), punto2(X2, Y2)
{ }

CRectangulo::~CRectangulo() { }

float CRectangulo::Perimetro()
{
CPunto punto3(punto2.GetX(), punto.GetY());
float longX = punto.DistanciaHasta(punto3);
float longY = punto2.DistanciaHasta(punto3);
return 2 * (longX + longY);
}

float CRectangulo::Area()
{
CPunto punto3(punto2.GetX(), punto.GetY());
float longX = punto.DistanciaHasta(punto3);
float longY = punto2.DistanciaHasta(punto3);
return longX * longY;
}

char * CRectangulo::Descripcion()
{
strcpy(desc, "\n Punto 1: "); strcat(desc, punto.Texto());
strcat(desc, "\n Punto 2: "); strcat(desc, punto2.Texto());
return desc;
}

5
 Archivo CTriangulo.h

#ifndef CTrianguloH
#define CTrianguloH
#include "CFigura.h"

class CTriangulo : public CFigura


{
protected:
CPunto punto2;
CPunto punto3;
public:
CTriangulo(float, float, float, float, float, float);
virtual ~CTriangulo();
virtual float Perimetro();
virtual float Area();
virtual char * Descripcion();
};
#endif

 Archivo CTriangulo.cpp

#include "CTriangulo.h"

CTriangulo::CTriangulo(float X1, float Y1, float X2, float Y2, float X3, float Y3)
: CFigura(X1, Y1), punto2(X2, Y2), punto3(X3, Y3)
{ }

CTriangulo::~CTriangulo() { }

float CTriangulo::Perimetro()
{
float lado1_2 = punto.DistanciaHasta(punto2);
float lado1_3 = punto.DistanciaHasta(punto3);
float lado2_3 = punto2.DistanciaHasta(punto3);
return lado1_2 + lado1_3 + lado2_3;
}

float CTriangulo::Area()
{
float S = Perimetro() / 2;
float a = punto.DistanciaHasta(punto2);
float b = punto.DistanciaHasta(punto3);
float c = punto2.DistanciaHasta(punto3);
return sqrt(S * (S - a) * (S - b) * (S - c));
}

char * CTriangulo::Descripcion()
{
strcpy(desc, "\n Punto 1: "); strcat(desc, punto.Texto());
strcat(desc, "\n Punto 2: "); strcat(desc, punto2.Texto());
strcat(desc, "\n Punto 3: "); strcat(desc, punto3.Texto());
return desc;
}

 Archivo CEditorFigura.h

6
#ifndef CEditorFiguraH
#define CEditorFiguraH
#include "CFigura.h"

class CEditorFigura
{
CFigura* *figs;
const int cantMax;
int cantReal;
public:
CEditorFigura(int = 500);
~CEditorFigura();
int GetCantFiguras();
CFigura* Figura(int pos);
bool Agregar(CFigura*);
float AreaTotal();
int CantCirculos();
};
#endif

 Archivo CEditorFigura.cpp

#include "CEditorFigura.h"
#include "CCirculo.h"
#include <typeinfo>

CEditorFigura::CEditorFigura(int max):cantMax(max)
{
cantReal = 0;
figs = new CFigura*[cantMax];

for (int i = 0; i < cantMax; i++)


figs[i] = 0;
}

CEditorFigura::~CEditorFigura()
{
for (int i = 0; i < cantReal; i++)
delete figs[i];
delete [] figs;
}

int CEditorFigura::GetCantFiguras()
{
return cantReal;
}

bool CEditorFigura::Agregar(CFigura* nueva)


{
if (cantReal < cantMax && nueva != 0)
{
figs[cantReal++] = nueva;
return true;
}
return false;
}

CFigura* CEditorFigura::Figura(int pos)

7
{
CFigura* pFig = NULL;
if (pos >= 0 && pos < cantReal)
pFig = figs[pos];
return pFig;
}

float CEditorFigura::AreaTotal()
{
float area = 0.0;
for (int i = 0; i < cantReal; i++)
area += figs[i]->Area();
return area;
}

int CEditorFigura::CantCirculos()
{
int cont = 0;
for (int i = 0; i < cantReal; i++)
if (typeid(*figs[i]) == typeid(CCirculo))
cont++;
return cont;
}

 Archivo main.cpp

#include <iostream.h>
#include "CCirculo.h"
#include "CRectangulo.h"
#include "CTriangulo.h"
#include "CEditorFigura.h"

int main()
{
CFigura *ptr;
CCirculo *c1 = new CCirculo(1.2, 3.4, 5.6);
CRectangulo *r1 = new CRectangulo(1.2, 2.3, 3.4, 4.5);
CTriangulo *t1 = new CTriangulo(1.2, 2.3, 3.4, 4.5, 5.6, 6.7);
ptr = r1;
CFigura *ptr2 = t1;
CEditorFigura E(3);

if (E.Agregar(c1))
cout << "Figura agregada.\n";
else
cout << "Figura no agregada.\n";

if (E.Agregar(ptr))
cout << "Figura agregada.\n";
else
cout << "Figura no agregada.\n";

if (E.Agregar(ptr2))
cout << "Figura agregada.\n";
else
cout << "Figura no agregada.\n";

CCirculo *c2 = new CCirculo(4.5, 5.6, 6.7);

8
if (E.Agregar(c2))
cout << "Figura agregada.\n";
else {
cout << "Figura no agregada.\n";
delete c2;
}

cout << "\nDatos de las figuras agregadas:\n";


for (int i = 0; i < E.GetCantFiguras(); i++)
cout << "\nFigura # " << i + 1 << ": "
<< typeid(*E.Figura(i)).name()
<< E.Figura(i)->Descripcion()
<< endl;

cout << "\nArea total de las figuras agregadas: "


<< E.AreaTotal() << " unidades cuadradas\n";

cout << "\nCantidad de circulos agregados: "


<< E.CantCirculos() << endl;

cout << "\nPerimetro de cada figura agregada:\n";


for (int i = 0; i < E.GetCantFiguras(); i++)
cout << " Figura # " << i + 1 << ": "
<< E.Figura(i)->Perimetro() << endl;

system("pause");
return 0;
}

Figura 2. Salida en consola del programa.

9
Conclusiones

En esta clase ejercitamos los contenidos vistos en la conferencia, identificando clases y


dentro de estas las funciones virtuales; dándosele solución a diferentes problemas donde se
manifestaba la herencia y el polimorfismo.

Ejercicios propuestos

Para cada uno de los siguientes problemas realice el diseño de clases y haga la
implementación en C++:

1. Modifique la implementación del ejercicio visto en la clase práctica anterior, de forma


tal que aproveche las ventajas del polimorfismo.

2. Se quiere conformar un equipo de fútbol a partir de cierto presupuesto para el pago de


los jugadores. Los jugadores pueden ser juveniles o mayores, representados
mediante la siguiente jerarquía de clases.

Juvenil

juegos
Juvenil
Pago

Mayor

goles
Mayor
Pago

Implemente la jerarquía en C++ teniendo en cuenta lo siguiente:

 Los atributos son privados y su valor debe establecerse mediante constructores.


 Los atributos juegos y goles almacenan la cantidad de juegos y goles de por vida de
un futbolista.
 El pago a un futbolista Juvenil es de 5 pesos por cada juego que tenga de por vida.
 El pago a un futbolista Mayor es de 500 pesos por su promedio de goles por juego,
excepto cuando esta cantidad es menor que 400 pesos, en cuyo caso se le pagarían
400 pesos.

La siguiente clase es la encargada de almacenar los futbolistas para un equipo. Complete la

10
clase Equipo agregándole un método Contratar, cuya función es agregar un futbolista al
listado del equipo. Contratar devolverá true o false en dependencia de si el jugador se
puede o no contratar. Un jugador se puede contratar si queda suficiente presupuesto para su
pago, y si la cantidad de jugadores ya contratados es menor que 20.

class Equipo
{
Juvenil* *jugadores;
int cantidad;
double presupuesto, prUsado;
public:
Equipo(double presup);
// Crear método Contratar

}

En el programa principal realice lo siguiente:


 Cree un equipo vacío.
 Cree jugadores con datos entrados por consola, estos puede ser de tipo Juvenil o
Mayor a opción del usuario.
 Después de crear el equipo, imprima el total de dinero que se les paga a los jugadores
mayores.

11

Potrebbero piacerti anche