introduccion a la poo (c++)

28
Capítulo I Indice rápido del capítulo 1: o Clases o Estructuras con funciones miembros.  o Definición de una clase, (class). o Constructores.  o Tipos de constructores.  o Sobrecarga de funciones, (polimorfismo).  o Funciones InLine. o Definición de una función miembro fuera de la clase. o Destructores. o Especificadores de acceso, (private, public, protected)  En esta sección abordaremos los conceptos básicos - iniciales, de la Programación Orientada a Objetos, (POO).  Se verán algunos conceptos como clases, polimorfismo, herencia, etc., directamente con ejemplos, sin utilizar muchas definiciones "académicas", tan sólo 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; }

Upload: luciano-carnevale

Post on 05-Jul-2015

177 views

Category:

Documents


0 download

TRANSCRIPT

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 1/28

 

Capítulo I 

Indice rápido del capítulo 1:

o

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

En esta sección abordaremos los conceptos básicos - iniciales, de la

Programación Orientada a Objetos, (POO). 

Se verán algunos conceptos como clases, polimorfismo, herencia, etc.,

directamente con ejemplos, sin utilizar muchas definiciones "académicas", tan sólo

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;

}

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 2/28

 

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; //Declaración de la variable coo de tipo Coordenadas 

coo.x=7; //Valores iniciales para los datos miembros. 

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 podría decir que una estructura es el "antepasado" más 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 además de def inir sus datos

miembros también definiera las funciones para manipularlos. Este tipo de

estructuras existe en C++ y se definen igual que las estructuras de C pero además

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

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 3/28

 

{int x,y,z;

void Cargar(void)  //Función miembro que carga los datos. {

x=8;y=9;z=10;}

void Mostrar(void)  //Función miembro que muestra el contenido de los datos. {cout << x <<endl;cout << y <<endl;cout << z <<endl;}

};

void main(void){

struct Coordenadas coo;  //Se define una variable, (coo), de tipo Coordenadas. 

coo.Cargar();  //Llamadas a las funciones de coo. coo.Mostrar();

 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){

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 4/28

 

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 públicos,

pero en una clase por defecto los datos miembros son privados, (esto forma parte,

entre otras cosas, de lo que se llama "encapsular"), y sólo las funciones públicas

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 hacía falta definir una clase, la versión de

la estructura es más que suficiente. 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 5/28

 

Pero cuando el concepto del objeto a crear es un tanto más complejo, y preocupa,

por ejemplo, la protección de los contenidos de los datos miembros, o se tiene una

gran cantidad de funciones miembros, o simplemente se pretende en serio

programar según POO, es cuando una clase se hace presente. 

Pues como supongo astutamente dedujo, la Programación 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 función miembro muy particular llamada Constructor.

Un constructor es una función que debe tener el mismo nombre que la clase y no

debe retornar ningún 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 ningún constructor definido, cuando

ocurre esto el compilador de C++ crea en ejecución 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 automáticamente cuando se crea la instancia, o s ea

que no hay llamarlo explícitamente desde el programa principal.  

Existen 3 tipos de constructores:

- Constructor por defecto. 

- Constructor común. 

- Constructor de copia. 

El constructor por defecto es, en caso que no lo haya definido, el que C++ en

tiempo de ejecución le asigne, o bien: 

class Coordenadas{

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 6/28

 

int x,y,z; 

public:Coordenadas();  //Constructor por defecto 

};

También le podríamos 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 común es aquel que recibe parámetros para asignarles como

valores iniciales a los datos miembros, o sea que al crear la instancia , se pasó

unos parámetros para inicializar. 

class Coordenadas{

int x,y,z; 

public:Coordenadas(int p, int q, int t) {x=p; y=q; z=t;}  //Constructor común. 

}; 

Cuando se crea el objeto se escribe:

void main(void)

{

Coordenadas coo(6,7,22); //Se le pasa los valores para inicializar. 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 7/28

 

.....

}

El constructor de copia se utilizan para inicializar un objeto con otro objeto de lamisma clase.

class Coordenadas{

int x,y,z; 

public:Coordenadas ( int p, int q, int t) {x=p; y=q; z=t;}  //Constructor común. 

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);  //Creación de un objeto con lo valores iniciales1, 2 y 3. 

Coordenadas coo=k;  //Se llama al constructor de copia para que le asignea coo los valores de k. 

.... } 

Sobrecarga de funciones, (polimorfismo): 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 8/28

 

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

copia , que también se define un constructor común . Bueno, eso es posible, una

clase puede tener varios constructores, que se irán usando de acuerdo a como

uno cree el objeto, (pasándole o no parámetros). 

Pero, observe nuevamente, esta vez más detalladamente, la clase..., ¿no

encuentra otra cosa extraña?. 

...(suspenso). : )

Los constructores son funciones, ¿¿¿cómo permite el compilador dos funciones

con el mismo nombre???.

 Ahh, buena pregunta.

El compilador de C++ permitiría 100 funciones con el mismo nombre, el único

requisito es que cada una de ellas tenga diferente número y/o tipo de parámetros.  

Esta cualidad, que no se aplica solamente a los constructores y funciones

miembros de una clase, sino que a cualquier función de un programa de C++, se

llama Sobrecarga de funciones o Polimorfismo .

Cuando se llama a la función, C++ selecciona de todas las funciones

sobrecargadas aquella que se ajusta de acuerdo con los parámetros pasados, en

cantidad y tipo.

Funciones InLine: 

También 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 están definidas fuera dela clase, dentro de esta última sólo se declararían los prototipos.  

En el caso que la función esté definida dentro de la clase, ésta se llama función

inline, como las funciones Cargar() y Mostrar() de nuestra clase Coordenadas. Se

podría incluso agregar la cláusula inline, pero no hace falta.  

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 9/28

 

¿Qué diferencia hay entre una función inline y otra, (definida dentro o fuera de la

clase)?

Se define una función inline cuando es muy corta y simple, como los constructores

y esas funciones del ejemplo. Declarar una función en línea significa que el

compilador puede, si así lo decide, reemplazar cada invocación por la función, con

la frecuencia que sea, por el código encerrado entre llaves. 

Hay que tener en cuenta que funciones inline extensas consumen más memoria, a

pesar que elimina el tiempo que lleva hacer la invocación.  

Cuando se escribe una función fuera de la clase se especifica el acceso de la

siguiente forma:

NombreClase::Función()  //Note que se accede con :: 

 Así quedaría 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;}  //Constructor por defecto. void Cargar(void);  //Prototipo de las funciones. void Mostrar(void);

};

void Coordenadas::Cargar(void)  //Definición de las funciones fuera de la clase {

x=8;

y=9;z=10;

}

void Coordenadas::Mostrar (void){

cout << x <<endl;cout << y <<endl;

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 10/28

 

cout << z <<endl;}

void main(void){

Coordenadas coo;

coo.Cargar();coo.Mostrar();

Destructores: 

Existe una función especial más para las clases, y se trata de los destructores.  

Un destructor es una función miembro que se llama cuando se destruye la clase.

Todas las clases tiene un destructor implícito, incluso aunque no esté declarado.

El destructor implícito no hace nada en particular, pero si uno quiere, puede

declarar un destructor de forma explícita. Su sintaxis sería:  

class NombreClase { 

... public: 

~NombreClase(); ... 

El destructor debe comenzar con el caracter "ñuflo", (~), seguido por el nombre de

la clase, (igual que el constructor). Además el destructor no puede recibir 

parámetros ni retornar nada, (ni siquiera void).

No puede haber más de un destructor para una clase y si no se define uno

explícitamente, el compilador crea uno automáticamente. 

El destructor se llama automáticamente siempre que una variable de ese tipo de

clase, (una instancia u objeto), sale fuera de su ámbito, (por ejemplo cuando

termina el programa).

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 11/28

 

Especificadores de acceso: 

Ya había dicho que por defecto los datos miembros de una clase son privados.

¿Qué significa esto?. 

Que sólo las funciones miembros públicas de la misma clase tienen acceso a 

ellos . Si lo desea puede escribir la cláusula private al momento de declarar los

datos.

En cambio la cláusula public es obligatoria cuando se desea declarar un dato

público y este dato estará disponible para cualquier función de l programa.

Existe una cláusula más, protected . Los datos definidos a continuación de esta

cláusula están restringidos para cualquier función externa a la clase, pero son

públicos para la propia clase y los miembros de clases derivadas. 

Capítulo II 

Indice rápido del capítulo 2:

o  Herencia. o  Tipos de herencias. o  Ejemplo de herencia. o  Accesibilidad de miembros en clases derivadas. 

HERENCIA:.

Una de las características más 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 código

en clases descendientes.

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 12/28

 

Cuando una clase se hereda de otra clase, la clase original se llama clase base y

la nueva clase se llama clase derivada. 

Quizás lo más difícil al escribir programas que utilicen clases, es el diseño de las

mismas, lo que involucra una abstracción del objeto que van a representar, pero

más difícil aún es diseñar una clase que luego sirva como "base" para nuevas

clases derivadas. Aquí además de la abstracción hay que seguir ciertas reglas de

accesibilidad, que más adelante de describen. 

Veamos un ejemplo:

Uno podría definir una clase CEmpleado, (a partir de aquí le agregaremos una C

al comienzo del nombre de la clase para guardar una relación estrecha con la

convención utilizada por Microsoft en su MFC). 

Esta clase, básica, solamente tendrá dos datos miembros: el Apellido y el Salario,

dos constructores comunes y dos métodos, (o funciones miembros), que nos

permitirán obtener el Apellido y el Salario del empleado.

 Así podría 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();

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 13/28

 

}; 

 //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 parámetros los

valores iniciales para el Apellido y el Salario, ya que el otro inicializa con cadena

vacía y 0, no es muy útil.

Luego si uno quiere saber cual es el apellido del empleado deberá usar la función

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 protección de la información. Las funciones ObtenerApellido() y ObtenerSalario() están definidas fuera de la

clase, aunque podrían haber sido InLine ya que son muy cortitas, sólo retornan el

dato miembro solicitado.

 Así que, como ejemplo se podría escribir, dentro de la función 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 diría, pero nos va a servir para

ejemplificar un caso sencillo de herencia.

Existen dos tipos de Herencia: 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 14/28

 

 

Simple : Una clase se deriva de sólo una clase base.  

Múltiple : Una clase se deriva de más de una clase base.  

Nuestro ejemplo será de herencia simple. 

 Ante todo una pregunta: ¿qué representa nuestra clase CEmpleado?. 

Bueno, la definimos con la intensión que represente un empleado cualquiera.

Empleados existen muchos, sea cual sea la empresa en la que trabajan, todos

tienen actividades específicas, por ejemplo un obrero, un jefe de sector, un

gerente, etc. CEmpleado es una clase, (por como la diseñamos, 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 disposición, etc. Por lo tanto

tenemos un pequeño problema con nuestra clase CEmpleado para poder 

representar un gerente, puesto que se limita solamente al Apellido y el Salario, nos

faltarían datos miembros para el departamento que tiene a su cargo y la

secretaria.

Podríamos 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 estaría mal, pero

sería redundante, pues podríamos 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> 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 15/28

 

 //Definición 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;} 

 //***********************************************  

 //Definición 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;

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 16/28

 

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 derivación de CGerente de CEmpleado:  

class CGerente:public CEmpleado 

La definición de CGerente con :public CEmpleado indica que CGerente heredará de

CEmpleado, de forma pública, 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 dederivación es: 

y el miembro en la clase basees: 

se obtiene un miembro: 

private 

private  inaccesible 

protected  private 

public  private 

protected private  inaccesible 

protected  protected 

public  protected 

public 

private  inaccesible 

protected  protected 

public  public 

Como reglas de esta tabla se extrae:

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 17/28

 

 

1) Los datos miembros privados no son derivables sea cual sea el modo de

derivación. 

2) Derivando en modo privado se obtienen miembros privados.

3) Derivando en modo protegido se obtienen miembros protegidos.

4) Derivando en modo público se respetan las características de los miembros de

la clase base.

En la función main se podría 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 métodos 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 métodos ObtenerApellido() y ObtenerSalario(), y sinembargo los podemos usar. Esto es la herencia. La posibilidad de poder reutilizar código. En la clase derivada sólo 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). 

Capítulo III 

Índice rápido del capítulo 3:

o  Jerarquía de clases. o  Clases abstractas. o  Funciones virtuales. o  Overriding. o  Ejemplo. o  La clase CFigura. o  La clase CRectangulo. 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 18/28

 

o  La clase CCirculo. o  Interfases. 

Jerarquía de clases. 

 A través de la herencia, (simple y compuesta), se puede diseñar una jerarquía de

clases creando una potente herramienta de desarrollo aplicable a diversos

sistemas sin necesidad de modificar código. 

La representación gráfica de una jerarquía de clases es idéntica a la de un

organigrama, esto es, una clase base fundamental al tope de la jerarquía y luego

las diversas ramificaciones de clases derivadas que a su vez son clases bases de

otras.

En el ejemplo del capítulo 2 creamos una pequeña jerarquía, (bastante pequeña

por cierto), basada en 2 clases. Cuando el diseño de la jerarquía involucra más

clases la dificultad se presenta a la hora de identificar las relaciones entre las

clases que hacen que se pueda formar una jerarquía. 

Clases abstractas. 

Existe una clase especial muy útil para crear jerarquías, o mejor digamos que es

muy típico usarla para diseñar jerarquías. Estas clases se llaman "clases

abstractas", son como cualquier otra, pero definidas con la intención de que sirvan

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 19/28

 

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 podría decir que una clase abstracta presenta la interfase común para los

objetos de clases derivadas.

Funciones virtuales, (overriding). 

Técnicamente una clase abstracta define por lo menos una función virtual, que es

aquella que puede ser rescrita en la clase derivada, (que heredó esa función

virtual). Una función virtual en una clase es solamente la definición del prototipo de  

la función precedida por la palabra reservada virtual  y no hay implementación de la

misma en esa clase, sino que queda a criterio de clases derivadas, si es aplicable,

la escritura de la implementación, (el desarrollo de la función). 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 identificaríamos la posibilidad de diseñar una

 jerarquía de clases como por ejemplo muestra la siguiente figura:

La clase CEmpleado definiría todas las características comunes a todos los

empleados, por ejemplo datos miembros como m_Apellido, m_Nombre, m_Edad,

m_Salario, y métodos como Despedir(), AumentarSalario(...), etc. Además definiría

funciones virtuales como AumentarComision(), (pensemos que sólo algunos

empleados cobran comisiones, por ejemplo los gerentes).

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 20/28

 

Cuando se herede CGerente de CEmpleado, esta clase heredará todos los datos

y funciones miembros de CEmpleado pudiendo además sobrescribir la función

virtual AumentarComision() y agregando, por ejemplo, datos miembros

particulares de esta clase como m_Secretaria, (supongamos nuevamente que sólo

el gerente tiene una secretaria a su disposición). 

Un ejemplo práctico. 

Pongamos los dedos sobre el teclado y realicemos un ejemplo.

Vamos a hacer un programa que nos permita manipular figuras geométricas, por 

lo menos dos, rectángulos y círculos. 

Veamos: tanto para un rectángulo como para un círculo podemos dibujarlo,

moverlo, especificarle un color, averiguar de que color es, obtener la superficie,

obtener el perímetro, etc. Todo esto son acciones que se pueden realizar con una

figura cualquiera, pero la superficie de un rectángulo no se calcula igual que la de

un círculo, tampoco el perímetro, tampoco se dibujan iguales. No obstante el

método de averiguar o especificar el color es igual para los dos. En programación,

las figuras, se entienden como comprendidas dentro de un rectángulo, así que

"mover un círculo o un rectángulo" significaría mover el rectángulo contenedor y

esto se puede extender para cualquier figura.

Podemos crear dos clases CRectangulo y CCirculo, (o talvez mejor CElipse), pero

repetiríamos mucho código ya que métodos como Mover(), GetColor(), SetColor()

son idénticos 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 tendría más

sentido, sería más prolijo y nos ahorraríamos algo de código.   Así que planifiquemos antes de empezar: 

La clase CFigura. 

Clase CFigura.

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 21/28

 

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; (inicializaría los datos miembros con 0). 

Destructor; (nada en particular)

Mover; (recibiría la nueva posición del punto x,y superior izquierdo). 

SetColor; (recibiría una variable de tipo RGB que contiene los valores

del nuevo color).

GetColor; (recibiría una referencia a RGB donde ubicaría los valores

del color actual).

Hasta aquí las funciones que debería definir e implementar CFigura, pero además

podría presentar como funciones virtuales, (o sea sólo el prototipo y no el

desarrollo), aquellas que también son comunes a todas las figuras pero cuyo

contenido varía, ejemplo Dibujar(), entonces le agregaríamos a CFigura: 

virtual Dibujar;

virtual Perímetro; 

virtual Superficie;

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

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 22/28

 

 

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 colóquele CFigura, acepte y escriba: 

 //CFigura.h: Definición 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 rectángulo donde está la figura

int top;int left;int bottom;int right;RGB m_color;

public: CFigura()  //constructor común{top=0;left=0;bottom=0;right=0;m_color.r=0;

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 23/28

 

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 derivadasvirtual void Dibujar() = 0;virtual double Perimetro() = 0; //Devuelve el perímetro de la figura.virtual double Superficie() = 0; //Devuelve la superficie de la figura.

}; 

Este es el archivo de cabecera CFigura.h con la definición de la clase, ahora nos

hace falta escribir la implementación 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: implementación 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;

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 24/28

 

}

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 posición (del rectángulo contenedor). left = x;top = y;right = x + ancho;bottom = y + alto; 

Note que en el archivo de implementación no están 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 diseñada para ser derivada y que ella misma expone un

interfase de lo que representa.

La clase CRectangulo. 

 Al derivar CRectagulo de forma pública de CFigura, heredará todos los datos

miembros y funciones miembros, (no virtuales), deberemos agregar como dato

miembro exclusivo del rectángulo la altura y la base y además sobrescribir las

funciones virtuales de CFigura.

Vaya nuevamente a File - New, seleccione C++ Header File, colóquele como

nombre CRectangulo, acepte y escriba:

 //CRectangulo.h: Definición de la clase CRectangulo. #include "math.h"

 //clase CRectangulo derivada de CFigura 

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 25/28

 

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 implementación de esta clase, (agregue un nuevo a rchivo C++

Source File con el nombre CRectangulo).

 //CRectangulo.cpp: implementación de la clase CRectangulo.#include "CFigura.h"#include "CRectangulo.h"#include "math.h"

#include "iostream.h"

 //funciones sobreescritas por CRectangulovoid CRectangulo::Dibujar(){cout << "Se dibuja un rectángulo en: ("<< left <<", "<< top <<") - ";cout <<"("<< right <<", " << bottom <<")"<<endl;

}

double CRectangulo::Superficie()

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 26/28

 

{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

función virtual de la clase base sin la palabra reservada virtual en la definición de

la clase CRectangulo, luego además se define, en este archivo de

implementación, el comportamiento específico de la función. 

La clase CCirculo. 

Y para la clase CCirculo también tenemos un archivo de cabecera CCirculo.h y un

archivo de implementación CCirculo.cpp: 

 //CCirculo.h: Definición 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();

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 27/28

 

  double Perimetro();}; 

 //CCirculo.cpp: implementación de la clase CCirculo.#include "CFigura.h"

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

 //funciones sobreescritas por CCirculovoid 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 más 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;

5/6/2018 Introduccion a La Poo (c++) - slidepdf.com

http://slidepdf.com/reader/full/introduccion-a-la-poo-c 28/28

 

r.Dibujar (); //dibujo el rectangulo. cout << "Superficie: "<<r.Superficie()<<endl; //Obtengo la supeficie.cout <<"Perimetro: "<<r.Perimetro ()<<endl; //Obtengo el perímetro. 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 perímetro. c.Mover(50,50); //Lo muevo. c.Dibujar(); //Lo vuelvo a dibujar. 

Desde ya que sería más interesante si la función 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 sólo de

funciones virtuales se las llama "Interfases" y son muy usadas en las

programación de componentes COM. Por ejemplo tenemos la clase/interfase

IUnknown. Pero esto ya es otro tema.