Вы находитесь на странице: 1из 9

Captulo III

ndice rpido del captulo 3:

o Jerarqua de clases.
o Clases abstractas.
o Funciones virtuales.
o Overriding.
o Ejemplo.
o La clase CFigura.
o La clase CRectangulo.
o La clase CCirculo.
o Interfases.

Jerarqua de clases.

A travs de la herencia, (simple y compuesta), se puede disear una jerarqua de clases


creando una potente herramienta de desarrollo aplicable a diversos sistemas sin
necesidad de modificar cdigo.
La representacin grfica de una jerarqua de clases es idntica a la de un organigrama,
esto es, una clase base fundamental al tope de la jerarqua y luego las diversas
ramificaciones de clases derivadas que a su vez son clases bases de otras.

En el ejemplo del captulo 2 creamos una pequea jerarqua, (bastante pequea por
cierto), basada en 2 clases. Cuando el diseo de la jerarqua involucra ms clases la
dificultad se presenta a la hora de identificar las relaciones entre las clases que hacen
que se pueda formar una jerarqua.

Clases abstractas.

Existe una clase especial muy til para crear jerarquas, o mejor digamos que es muy
tpico usarla para disear jerarquas. Estas clases se llaman "clases abstractas", son
como cualquier otra, pero definidas con la intencin de que sirvan como clase base de
otras clases. O sea que nunca se va a crear una instancia de una clase abstracta, (nunca
se crear un objeto de esa clase).
Se podra decir que una clase abstracta presenta la interfase comn para los objetos de
clases derivadas.
Funciones virtuales, (overriding).

Tcnicamente una clase abstracta define por lo menos una funcin virtual, que es
aquella que puede ser rescrita en la clase derivada, (que hered esa funcin virtual). Una
funcin virtual en una clase es solamente la definicin del prototipo de la funcin
precedida por la palabra reservada virtual y no hay implementacin de la misma en esa
clase, sino que queda a criterio de clases derivadas, si es aplicable, la escritura de la
implementacin, (el desarrollo de la funcin). Esto es overriding.
Imaginemos que necesitamos escribir un programa para gestionar liquidaciones de
sueldos en una empresa grande y queremos aplicar nuestro conocimientos en POO.
Seguramente muy pronto identificaramos la posibilidad de disear una jerarqua de
clases como por ejemplo muestra la siguiente figura:

La clase CEmpleado definira todas las caractersticas comunes a todos los empleados,
por ejemplo datos miembros como m_Apellido, m_Nombre, m_Edad, m_Salario, y
mtodos como Despedir(), AumentarSalario(...), etc. Adems definira funciones
virtuales como AumentarComision(), (pensemos que slo algunos empleados cobran
comisiones, por ejemplo los gerentes).
Cuando se herede CGerente de CEmpleado, esta clase heredar todos los datos y
funciones miembros de CEmpleado pudiendo adems sobrescribir la funcin virtual
AumentarComision() y agregando, por ejemplo, datos miembros particulares de esta
clase como m_Secretaria, (supongamos nuevamente que slo el gerente tiene una
secretaria a su disposicin).

Un ejemplo prctico.

Pongamos los dedos sobre el teclado y realicemos un ejemplo.


Vamos a hacer un programa que nos permita manipular figuras geomtricas, por lo
menos dos, rectngulos y crculos.
Veamos: tanto para un rectngulo como para un crculo podemos dibujarlo, moverlo,
especificarle un color, averiguar de que color es, obtener la superficie, obtener el
permetro, etc. Todo esto son acciones que se pueden realizar con una figura cualquiera,
pero la superficie de un rectngulo no se calcula igual que la de un crculo, tampoco el
permetro, tampoco se dibujan iguales. No obstante el mtodo de averiguar o especificar
el color es igual para los dos. En programacin, las figuras, se entienden como
comprendidas dentro de un rectngulo, as que "mover un crculo o un rectngulo"
significara mover el rectngulo contenedor y esto se puede extender para cualquier
figura.
Podemos crear dos clases CRectangulo y CCirculo, (o talvez mejor CElipse), pero
repetiramos mucho cdigo ya que mtodos como Mover(), GetColor(), SetColor() son
idnticos en ambas clases. Pero qu si creamos una clase abstracta llamada CFigura que
contenga todas las definiciones de las acciones comunes a todas las figuras y luego
derivar las clases CRectangulo y CCirculo de ella. Esto tendra ms sentido, sera ms
prolijo y nos ahorraramos algo de cdigo.
As que planifiquemos antes de empezar:

La clase CFigura.

Clase CFigura.
datos miembros:
int left; (x de la coordenada superior izquierda).
int top; (y de la coordenada superior izquierda).
int right; (x de la coordenada inferior derecha).
int bottom; (y de la coordenada inferior derecha).
RGB m_color; (variable de estructura tipo RGB para almacenar los valores
del color).
funciones miembros:
Constructor; (inicializara los datos miembros con 0).
Destructor; (nada en particular)
Mover; (recibira la nueva posicin del punto x,y superior izquierdo).
SetColor; (recibira una variable de tipo RGB que contiene los valores del
nuevo color).
GetColor; (recibira una referencia a RGB donde ubicara los valores del
color actual).

Hasta aqu las funciones que debera definir e implementar CFigura, pero adems podra
presentar como funciones virtuales, (o sea slo el prototipo y no el desarrollo), aquellas
que tambin son comunes a todas las figuras pero cuyo contenido vara, ejemplo
Dibujar(), entonces le agregaramos a CFigura:

virtual Dibujar;
virtual Permetro;
virtual Superficie;

Los datos miembro left, top, right, bottom son los puntos (x,y) de cada extremo del
rectngulo contenedor de una figura:

Ya tenemos una idea de nuestra clase CFigura, entonces vaya, en Visual C++, a File -
New y seleccione un proyecto Win32 Console Application, (en blanco).
Una vez creado el proyecto vaya a File - New y seleccione C++ Header File y como
nombre al archivo colquele CFigura, acepte y escriba:
//CFigura.h: Definicin de la clase CFigura.

#define PI 3.1416 //constante PI

//Estructura para el color.


struct RGB
{
int r;
int g;
int b;
};

//clase abstracta CFigura


class CFigura
{
protected: //datos miembros que representan el rectngulo donde
est la figura
int top;
int left;
int bottom;
int right;
RGB m_color;
public:
CFigura() //constructor comn
{
top=0;
left=0;
bottom=0;
right=0;
m_color.r=0;
m_color.g=0;
m_color.b=0;
}
~CFigura()
{
//por ahora nada en el destructor
}

void Mover(int x, int y /*Del extremo superior izquierdo*/); //Mueve


la figura.
void SetColor(RGB newColor); //Establece color de la figura.
void GetColor(RGB& curColor); //Obtiene el color actual de la figura.

//funciones virtuales a sobreescribir por clases derivadas


virtual void Dibujar() = 0;
virtual double Perimetro() = 0; //Devuelve el permetro de la figura.
virtual double Superficie() = 0; //Devuelve la superficie de la figura.
};
Este es el archivo de cabecera CFigura.h con la definicin de la clase, ahora nos hace
falta escribir la implementacin de la clase o sea el archivo .cpp con las funciones
definidas por esta clase.
Vaya a File - New y agregue un archivo C++ Source File de nombre CFigura y escriba:

//CFigura.cpp: implementacin de la clase CFigura.


#include "CFigura.h"
#include "math.h"

void CFigura::SetColor(RGB newColor)


{
m_color.r=newColor.r;
m_color.g=newColor.g;
m_color.b = newColor.b;
}

void CFigura::GetColor(RGB& curColor)


{
curColor.r =m_color.r;
curColor.g = m_color.g;
curColor.b = m_color.b;
}

void CFigura::Mover (int x, int y)


{
//Obtengo las dimensiones de la figura.
int ancho = abs(right - left);
int alto = abs(bottom - top);

//Calculo la nueva posicin (del rectngulo contenedor).


left = x;
top = y;
right = x + ancho;
bottom = y + alto;
}

Note que en el archivo de implementacin no estn desarrolladas las funciones virtuales


y es as porque la clase abstracta solamente "expone" los prototipos de funciones
virtuales para que cada clase derivada la sobrescriba, (overriding), en caso de ser
necesario.
Cuando uno ve una clase con funciones virtuales tiene que estar seguro que se trata de
una clase diseada para ser derivada y que ella misma expone un interfase de lo que
representa.

La clase CRectangulo.
Al derivar CRectagulo de forma pblica de CFigura, heredar todos los datos miembros
y funciones miembros, (no virtuales), deberemos agregar como dato miembro exclusivo
del rectngulo la altura y la base y adems sobrescribir las funciones virtuales de
CFigura.
Vaya nuevamente a File - New, seleccione C++ Header File, colquele como nombre
CRectangulo, acepte y escriba:

//CRectangulo.h: Definicin de la clase CRectangulo.


#include "math.h"
//clase CRectangulo derivada de CFigura
class CRectangulo:public CFigura
{
protected:
int altura;
int base;
public:
CRectangulo(int x1, int y1, int x2, int y2, int rojo, int verde, int
azul)
{
top=y1;
left=x1;
bottom=y2;
right=x2;
altura=y2-y1;
base=x2-y1;
m_color.r=rojo;
m_color.g=verde;
m_color.b=azul;
}

~CRectangulo()
{
//por ahora nada en el constructor
}
//Funciones sobrescritas.
void Dibujar();
double Superficie();
double Perimetro();
};

Ahora el archivo de implementacin de esta clase, (agregue un nuevo archivo C++


Source File con el nombre CRectangulo).

//CRectangulo.cpp: implementacin de la clase CRectangulo.


#include "CFigura.h"
#include "CRectangulo.h"
#include "math.h"
#include "iostream.h"
//funciones sobreescritas por CRectangulo
void CRectangulo::Dibujar()
{
cout << "Se dibuja un rectngulo en: ("<< left <<", "<< top <<") -
";
cout <<"("<< right <<", " << bottom <<")"<<endl;
}

double CRectangulo::Superficie()
{
double sup;
sup= (double)(base*altura)/2;
return sup;
}

double CRectangulo::Perimetro()
{
return (double)(base)*2 + (altura)*2;
}

El overriding tiene lugar al momento de declarar nuevamente el prototipo de la funcin


virtual de la clase base sin la palabra reservada virtual en la definicin de la clase
CRectangulo, luego adems se define, en este archivo de implementacin, el
comportamiento especfico de la funcin.

La clase CCirculo.

Y para la clase CCirculo tambin tenemos un archivo de cabecera CCirculo.h y un


archivo de implementacin CCirculo.cpp:

//CCirculo.h: Definicin de la clase CCirculo.


//clase CCirculo derivada de CFigura

class CCirculo:public CFigura


{
protected:
double radio;
public:
CCirculo (int x1, int y1, int x2, int y2, int rojo, int verde, int azul)
{
top=y1;
left=x1;
bottom=y2;
right=x2;
radio= (x2-x1)/2;
m_color.r=rojo;
m_color.g=verde;
m_color.b=azul;
}
~CCirculo()
{
//por ahora nada en el destructor
}
void Dibujar();
double Superficie();
double Perimetro();
};

//CCirculo.cpp: implementacin de la clase CCirculo.


#include "CFigura.h"
#include "CCirculo.h"
#include "math.h"
#include "iostream.h"

//funciones sobreescritas por CCirculo


void CCirculo::Dibujar ()
{
cout << "Se dibuja un circulo en: ("<< left <<", "<< top <<") - ";
cout <<"("<< right <<", " << bottom <<")"<<endl;
}

double CCirculo::Superficie ()
{
double sup;
sup= (double) PI * pow(radio,2);
return sup;
}

double CCirculo::Perimetro ()
{
return (double) 2*PI * radio;
}

Para probar estas clase agregaremos una vez ms un archivo C++ Source File, (yo le
puse de nombre "ejemplo7", pero puede ser cualquiera).
All escriba:

//Ejemplo de Overriding.
//Autor: Demian Panello.
//Yerba Mate y Visual C++ -> www.dcp.com.ar

#include "iostream.h"
#include "CFigura.h"
#include "CRectangulo.h"
#include "CCirculo.h"

void main(void)
{
CRectangulo r(2,2, 6,8, 255,0,0);
CCirculo c(0,0,10,10, 0,0,255);
RGB fc;

cout <<"**** Datos del rectangulo ****"<<endl;


r.Dibujar (); //dibujo el rectangulo.
cout << "Superficie: "<<r.Superficie()<<endl; //Obtengo la supeficie.
cout <<"Perimetro: "<<r.Perimetro ()<<endl; //Obtengo el
permetro.
r.GetColor(fc);
cout << "Color del rectangulo: " << fc.r << fc.g << fc.b<<endl;
//Obtengo el color.

cout <<"**** Datos del circulo ****"<<endl;


c.Dibujar(); //Dibujo un circulo.
cout << "Superficie: "<<c.Superficie()<<endl; //Obtengo la
superficie.
cout <<"Perimetro: "<< c.Perimetro ()<<endl; //Obtengo el
permetro.
c.Mover(50,50); //Lo muevo.
c.Dibujar(); //Lo vuelvo a dibujar.
}

Desde ya que sera ms interesante si la funcin dibujar de cada clase realmente


dibujara en lugar de mostrar un mensaje, pero eso se lo dejo a usted para que lo
investigue.

Finalmente queda por decir que a aquellas clases abstractas compuestas slo de
funciones virtuales se las llama "Interfases" y son muy usadas en las programacin de
componentes COM. Por ejemplo tenemos la clase/interfase IUnknown. Pero esto ya es
otro tema.

Вам также может понравиться