Sunteți pe pagina 1din 28

Captulo I

Indice rpido del captulo 1:


o o o o o o o o o o Clases Estructuras con funciones miembros. Definicin de una clase, (class). Constructores. Tipos de constructores. Sobrecarga de funciones, (polimorfismo). Funciones InLine. Definicin de una funcin miembro fuera de la clase. Destructores. Especificadores de acceso, (private, public, protected)

En esta seccin abordaremos los conceptos bsicos - iniciales, de la Programacin Orientada a Objetos, (POO). Se vern algunos conceptos como clases, polimorfismo, herencia, etc., directamente con ejemplos, sin utilizar muchas definiciones "acadmicas", tan slo ejemplos. Clases: En lenguaje C tradicional existen las estructuras de datos, las cuales se definen con la palabra clave struct, ejemplo: struct Coordenadas { int x; int y; int z; }

Con una estructura uno crea un tipo de dato nuevo, en este caso, se puede declarar una variable de tipo Coordenadas, la cual puede almacenar 3 valores enteros: struct Coordenadas coo; coo.x=7; coo.y=15; coo.z=55; x, y, z son los "datos miembros" de la estructura. Para manipular estos datos, (asignarles un valor inicial, cargarlos, mostrarlos, etc.), uno puede escribir funciones globales en su programa. Ejemplo: void Carga(void) void Muestra(void) Bueno, se podra decir que una estructura es el "antepasado" ms directo de una clase. Por qu?. Que tal si las funciones con las cuales uno manipula los datos de la estructura formaran parte de ella, o sea, una estructura tal que adems de definir sus datos miembros tambin definiera las funciones para manipularlos. Este tipo de estructuras existe en C++ y se definen igual que las estructuras de C pero adems uno puede declarar las funciones. Mire el siguiente ejemplo: (para estos ejemplos puede usar Visual C++ o Borland C++ 3.1, con cualquiera de ellos funcionan). //Estructura con funciones miembros. //Autor: Demian C. Panello. #include <iostream.h> struct Coordenadas //Declaracin de la variable coo de tipo Coordenadas //Valores iniciales para los datos miembros.

{ int x,y,z; void Cargar(void) { x=8; y=9; z=10; } void Mostrar(void) { cout << x <<endl; cout << y <<endl; cout << z <<endl; } }; //Funcin miembro que carga los datos.

//Funcin miembro que muestra el contenido de los datos.

void main(void) { struct Coordenadas coo; coo.Cargar(); coo.Mostrar(); }

//Se define una variable, (coo), de tipo Coordenadas. //Llamadas a las funciones de coo.

Ahora examine el siguiente programa y encuentre las diferencias con el anterior: //Lo mismo pero con una clase. //Autor: Demian C. Panello. #include <iostream.h> class Coordenadas { int x,y,z; public: void Cargar(void) { x=8; y=9; z=10; } void Mostrar(void) {

cout << x <<endl; cout << y <<endl; cout << z <<endl; } }; void main(void) { Coordenadas coo; coo.Cargar(); coo.Mostrar(); } Encontr las diferencias?. La verdad, no son muchas. En lugar de struct se pone class, luego se agrega la etiqueta public, antes de definir las funciones miembros, ya que para una estructura los datos miembros y funciones miembros son por defecto pblicos, pero en una clase por defecto los datos miembros son privados, (esto forma parte, entre otras cosas, de lo que se llama "encapsular"), y slo las funciones pblicas pueden tener acceso a los datos privados. Y la otra diferencia es en el momento de definir(*) la variable coo, no hace falta especificar la palabra class as como se hizo con struct. (*) En la POO, utilizando clases, ya no se habla de "definir" una variable de una clase en particular, sino que se crea una "instancia" o un objeto de dicha clase.

Por qu usar clases y no estructuras?.


A veces la diferencia, aparte de la sintaxis, no es del todo "pesada" como para justificar una clase. En este ejemplo no haca falta definir una clase, la versin de la estructura es ms que suficiente.

Pero cuando el concepto del objeto a crear es un tanto ms complejo, y preocupa, por ejemplo, la proteccin de los contenidos de los datos miembros, o se tiene una gran cantidad de funciones miembros, o simplemente se pretende en serio programar segn POO, es cuando una clase se hace presente. Pues como supongo astutamente dedujo, la Programacin Orientada a Objetos, consta de objetos, y una clase, define o es como la "plantilla" sobre la cual se construyen los tan mentados. Constructores: En una clase existe una funcin miembro muy particular llamada Constructor. Un constructor es una funcin que debe tener el mismo nombre que la clase y no debe retornar ningn valor, (ni siquiera void), y se encarga de asignarle valores iniciales, (o simplemente inicializar), a los datos miembros. En el ejemplo descubrir que all no hay ningn constructor definido, cuando ocurre esto el compilador de C++ crea en ejecucin el constructor. No obstante hubiera sido correcto haber definido un constructor que se encargara de, por ejemplo, inicializar con 0 los datos miembros. Un constructor es invocado automticamente cuando se crea la instancia, o sea que no hay llamarlo explcitamente desde el programa principal. Existen 3 tipos de constructores: - Constructor por defecto. - Constructor comn. - Constructor de copia. El constructor por defecto es, en caso que no lo haya definido, el que C++ en tiempo de ejecucin le asigne, o bien: class Coordenadas {

int x,y,z; public: Coordenadas(); }; Tambin le podramos haber agregado a este constructor, encerrados entre llaves, los valores iniciales para los datos: {x=0;y=0;z=0;}. Cuando se crea el objeto se escribe: void main(void) { Coordenadas coo; .... } El constructor comn es aquel que recibe parmetros para asignarles como valores iniciales a los datos miembros, o sea que al crear la instancia, se pas unos parmetros para inicializar. class Coordenadas { int x,y,z; public: Coordenadas(int p, int q, int t) {x=p; y=q; z=t;} }; Cuando se crea el objeto se escribe: void main(void) { Coordenadas coo(6,7,22); //Se le pasa los valores para inicializar.

//Constructor por defecto

//Constructor comn.

..... } El constructor de copia se utilizan para inicializar un objeto con otro objeto de la misma clase. class Coordenadas { int x,y,z; public: Coordenadas ( int p, int q, int t) {x=p; y=q; z=t;} //Constructor comn. Coordenadas(const Coordenadas c) //Constructor de copia.
{ x=c.x; y=c.y; z=c.z; }

}; Cuando se crea el objeto se escribe: void main(void) { Coordenadas k(1,2,3); 1, 2 y 3. Coordenadas coo=k; a coo los valores de k. .... }

//Creacin de un objeto con lo valores iniciales //Se llama al constructor de copia para que le asigne

Sobrecarga de funciones, (polimorfismo):

Habr advertido en el ltimo ejemplo de la clase, donde se ve el constructor de

copia, que tambin se define un constructor comn. Bueno, eso es posible, una
clase puede tener varios constructores, que se irn usando de acuerdo a como uno cree el objeto, (pasndole o no parmetros). Pero, observe nuevamente, esta vez ms detalladamente, la clase..., no encuentra otra cosa extraa?. ...(suspenso). : ) Los constructores son funciones, cmo permite el compilador dos funciones con el mismo nombre???. Ahh, buena pregunta. El compilador de C++ permitira 100 funciones con el mismo nombre, el nico requisito es que cada una de ellas tenga diferente nmero y/o tipo de parmetros. Esta cualidad, que no se aplica solamente a los constructores y funciones miembros de una clase, sino que a cualquier funcin de un programa de C++, se llama Sobrecarga de funciones o Polimorfismo. Cuando se llama a la funcin, C++ selecciona de todas las funciones sobrecargadas aquella que se ajusta de acuerdo con los parmetros pasados, en cantidad y tipo. Funciones InLine: Tambin se puede estar preguntando, si las funciones miembros de una clase pueden estar definidas fuera de la clase. La respuesta es s, por lo general las funciones miembros estn definidas fuera de la clase, dentro de esta ltima slo se declararan los prototipos. En el caso que la funcin est definida dentro de la clase, sta se llama funcin inline, como las funciones Cargar() y Mostrar() de nuestra clase Coordenadas. Se podra incluso agregar la clusula inline, pero no hace falta.

Qu diferencia hay entre una funcin inline y otra, (definida dentro o fuera de la clase)? Se define una funcin inline cuando es muy corta y simple, como los constructores y esas funciones del ejemplo. Declarar una funcin en lnea significa que el compilador puede, si as lo decide, reemplazar cada invocacin por la funcin, con la frecuencia que sea, por el cdigo encerrado entre llaves. Hay que tener en cuenta que funciones inline extensas consumen ms memoria, a pesar que elimina el tiempo que lleva hacer la invocacin. Cuando se escribe una funcin fuera de la clase se especifica el acceso de la siguiente forma: NombreClase::Funcin() //Note que se accede con ::

As quedara nuestro programa, con la clase con un constructor por defecto y con las funciones miembro fuera de la clase. #include <iostream.h> class Coordenadas { int x,y,z; public: Coordenadas(){x=0;y=0;z=0;} void Cargar(void); void Mostrar(void); }; void Coordenadas::Cargar(void) { x=8; y=9; z=10; } void Coordenadas::Mostrar (void) { cout << x <<endl; cout << y <<endl;

//Constructor por defecto. //Prototipo de las funciones.

//Definicin de las funciones fuera de la clase

cout << z <<endl; } void main(void) { Coordenadas coo; coo.Cargar(); coo.Mostrar(); } Destructores: Existe una funcin especial ms para las clases, y se trata de los destructores. Un destructor es una funcin miembro que se llama cuando se destruye la clase. Todas las clases tiene un destructor implcito, incluso aunque no est declarado. El destructor implcito no hace nada en particular, pero si uno quiere, puede declarar un destructor de forma explcita. Su sintaxis sera: class NombreClase { ... public: ~NombreClase(); ... } El destructor debe comenzar con el caracter "uflo", (~), seguido por el nombre de la clase, (igual que el constructor). Adems el destructor no puede recibir parmetros ni retornar nada, (ni siquiera void). No puede haber ms de un destructor para una clase y si no se define uno explcitamente, el compilador crea uno automticamente. El destructor se llama automticamente siempre que una variable de ese tipo de clase, (una instancia u objeto), sale fuera de su mbito, (por ejemplo cuando termina el programa).

Especificadores de acceso: Ya haba dicho que por defecto los datos miembros de una clase son privados. Qu significa esto?.

Que slo las funciones miembros pblicas de la misma clase tienen acceso a ellos. Si lo desea puede escribir la clusula private al momento de declarar los
datos. En cambio la clusula public es obligatoria cuando se desea declarar un dato pblico y este dato estar disponible para cualquier funcin del programa. Existe una clusula ms, protected. Los datos definidos a continuacin de esta clusula estn restringidos para cualquier funcin externa a la clase, pero son pblicos para la propia clase y los miembros de clases derivadas.

Captulo II
Indice rpido del captulo 2:
o o o o Herencia. Tipos de herencias. Ejemplo de herencia. Accesibilidad de miembros en clases derivadas.

HERENCIA:. Una de las caractersticas ms importantes de la POO, es la capacidad de derivar clases a partir de las clases existentes, (o sea obtener una nueva clase a partir de otra). Este procedimiento se denomina Herencia, puesto que la nueva clase "hereda" los miembros, (datos y funciones) de sus clases ascendientes y puede anular alguna de las funciones heredadas. La herencia permite reutilizar el cdigo en clases descendientes.

Cuando una clase se hereda de otra clase, la clase original se llama clase base y la nueva clase se llama clase derivada. Quizs lo ms difcil al escribir programas que utilicen clases, es el diseo de las mismas, lo que involucra una abstraccin del objeto que van a representar, pero ms difcil an es disear una clase que luego sirva como "base" para nuevas clases derivadas. Aqu adems de la abstraccin hay que seguir ciertas reglas de accesibilidad, que ms adelante de describen. Veamos un ejemplo: Uno podra definir una clase CEmpleado, (a partir de aqu le agregaremos una C al comienzo del nombre de la clase para guardar una relacin estrecha con la convencin utilizada por Microsoft en su MFC). Esta clase, bsica, solamente tendr dos datos miembros: el Apellido y el Salario, dos constructores comunes y dos mtodos, (o funciones miembros), que nos permitirn obtener el Apellido y el Salario del empleado. As podra ser la clase CEmpleado: class CEmpleado { protected: char ape[20]; double sueldo; public: CEmpleado() { strcpy(ape, ""); sueldo=0; } CEmpleado(char ap[20], double s) { strcpy(ape, ap); sueldo=s; } char* ObtenerApellido(); double ObtenerSueldo();

}; //funciones miembros de CEmpleado char* CEmpleado::ObtenerApellido () { return ape; } double CEmpleado::ObtenerSueldo () { return sueldo; }

Un programa que cree una instancia de esta clase, deber usar alguno de los dos constructores, se puede aprovechar el constructor que recibe como parmetros los valores iniciales para el Apellido y el Salario, ya que el otro inicializa con cadena vaca y 0, no es muy til. Luego si uno quiere saber cual es el apellido del empleado deber usar la funcin ObtenerApellido() ya que los datos miembros son protegidos y "no se ven" en el programa, (esto es "encapsulamiento"). Ofrecemos funciones para acceder a los datos miembros, a modo de proteccin de la informacin. Las funciones ObtenerApellido() y ObtenerSalario() estn definidas fuera de la clase, aunque podran haber sido InLine ya que son muy cortitas, slo retornan el dato miembro solicitado. As que, como ejemplo se podra escribir, dentro de la funcin main(), lo siguiente: CEmpleado e("Perez", 1260.35); cout << "Apellido: " << e.ObtenerApellido() << endl; cout <<"Salario: " << e.ObtenerSalario() << endl; Hasta aqu una clase sencilla y hasta muy poco til dira, pero nos va a servir para ejemplificar un caso sencillo de herencia. Existen dos tipos de Herencia:

Simple: Una clase se deriva de slo una clase base. Mltiple: Una clase se deriva de ms de una clase base.
Nuestro ejemplo ser de herencia simple. Ante todo una pregunta: qu representa nuestra clase CEmpleado?. Bueno, la definimos con la intensin que represente un empleado cualquiera. Empleados existen muchos, sea cual sea la empresa en la que trabajan, todos tienen actividades especficas, por ejemplo un obrero, un jefe de sector, un gerente, etc. CEmpleado es una clase, (por como la diseamos, aunque sea muy simple), que no hace diferencias entre los empleados, es, digamos, una clase general. Ahora bien, por lo general, un gerente, (que como dijimos, es un empleado), tiene atributos particulares que lo hace diferente a otro empleado, por ejemplo tiene a su cargo un departamento, tiene una secretaria a su disposicin, etc. Por lo tanto tenemos un pequeo problema con nuestra clase CEmpleado para poder representar un gerente, puesto que se limita solamente al Apellido y el Salario, nos faltaran datos miembros para el departamento que tiene a su cargo y la secretaria. Podramos definir una nueva clase CGerente con los datos miembros Apellido, Salario, Dpto, Secretaria y las funciones miembros ObtenerApellido(), ObtenerSalario(), ObtenerDpto() y ObtenerSecretaria(). S y no estara mal, pero sera redundante, pues podramos derivar la nueva clase CGerente de CEmpleado, puesto que los datos y funciones miembros nos resultan tiles. Derivemos, entonces, la clase CGerente de CEmpleado: #include <iostream.h> #include <string.h>

//Definicin de la clase CEmpleado //*************************************** class CEmpleado { protected: char ape[20]; double sueldo; public: CEmpleado() { strcpy(ape, ""); sueldo=0; } CEmpleado(char ap[20], double s) { strcpy(ape, ap); sueldo=s; } char* ObtenerApellido(); double ObtenerSueldo(); }; //funciones miembros de CEmpleado char* CEmpleado::ObtenerApellido () { return ape; } double CEmpleado::ObtenerSueldo () { return sueldo; } //*********************************************** //Definicin de la clase CGerente heredada de CEmpleado //******************************************************************** class CGerente:public CEmpleado (1) { char dpto[20]; char secretaria[20]; public: CGerente(char n[20], double s, char d[20], char sec[20]) { strcpy(ape, n); sueldo=s;

strcpy(dpto,d); strcpy(secretaria, sec); } char* ObtenerSecretaria(); char* ObtenerDpto(); }; //Funciones miembros de CGerente char* CGerente::ObtenerSecretaria() { return secretaria; } char* CGerente::ObtenerDpto () { return dpto; } Justamente en (1) es donde tiene lugar la derivacin de CGerente de CEmpleado: class CGerente:public CEmpleado La definicin de CGerente con :public CEmpleado indica que CGerente heredar de CEmpleado, de forma pblica, todos los datos y funciones miembros. El operador public en esta sentencia permite definir la accesibilidad de los datos miembros derivados. Una clase hereda de otra todos los datos y funciones miembros que no sean privados. Lo que sigue es una tabla que permite reconocer la accesibilidad en clases derivadas:
si el modo de derivacin es: private y el miembro en la clase base es: private protected public private protected protected public private public protected public

se obtiene un miembro: inaccesible private private inaccesible protected protected inaccesible protected public

Como reglas de esta tabla se extrae:

1) Los datos miembros privados no son derivables sea cual sea el modo de derivacin. 2) Derivando en modo privado se obtienen miembros privados. 3) Derivando en modo protegido se obtienen miembros protegidos. 4) Derivando en modo pblico se respetan las caractersticas de los miembros de la clase base. En la funcin main se podra escribir, para probar la funcionalidad de nuestra nueva clase derivada, lo siguiente:
void main(void) { CGerente g("Perez", 2500.60, "Sistemas", "Juana"); cout << g.ObtenerApellido()<<endl; cout << g.ObtenerSueldo()<<endl; cout << g.ObtenerDpto()<<endl; cout << g.ObtenerSecretaria()<<endl; }

Creamos una instancia de CGerente y probamos los mtodos de la clase. Hay que destacar que cuando definimos la clase CGerente no escribimos nada con respecto a los atributos Apellido y Salario y los mtodos ObtenerApellido() y ObtenerSalario(), y sin embargo los podemos usar. Esto es la herencia. La posibilidad de poder reutilizar cdigo. En la clase derivada slo hay que definir los datos y funciones miembros exclusivos de esa clase, (en nuestro ejemplo el nombre del Dpto y la secretaria y las funciones que permiten obtener estos valores).

Captulo III
ndice rpido del captulo 3:
o o o o o o o Jerarqua de clases. Clases abstractas. Funciones virtuales. Overriding. Ejemplo. La clase CFigura. La clase CRectangulo.

o o

La clase CCirculo. 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.

S-ar putea să vă placă și