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.