PROGRAMACION I
MONOGRAFÍA
INTEGRANTES: JHONNY CASILLAS
HENRY CARRERA
ROBERTH JUMBO
JUAN TONGUINO
29 DE JULIO DE 2015
SANGOLQUÍ
Contenido
1. FUNCIONES Y CLASES VIRTUALES...................................................................................... 3
2. CLASES ABSTRACTAS ............................................................................................................. 4
Reglas de uso: ................................................................................................................................. 4
Restricciones de acceso en C++ ...................................................................................................... 5
3. POLIMORFISMO ......................................................................................................................... 5
Clasificación .................................................................................................................................... 6
Diferencias entre polimorfismo y sobrecarga ............................................................................... 6
CONCLUCIONES ............................................................................................................................ 14
BIBLIOGRAFÍA ............................................................................................................................... 14
3
1. FUNCIONES Y CLASES VIRTUALES.
Para que la ligadura dinámica tenga efecto en una función particular, C++ necesita que se
use la palabra reservada virtual cuando se declara la función en la clase base. La ligadura
en tiempo de ejecución funciona únicamente con las funciones virtual es, y sólo cuando
se está usando una dirección de la clase base donde exista la función virtual, aunque
puede ser definida también en una clase base anterior.
Para crear una función miembro como virtual, simplemente hay que preceder a la
declaración de la función con la palabra reservada virtual. Sólo la declaración necesita la
palabra reservada virtual, y no la definición. Si una función es declarada como virtual,
en la clase base, será entonces virtual en todas las clases derivadas. La redefinición de
una función virtual en una clase derivada se conoce como overriding.
Hay que hacer notar que sólo es necesario declarar la función como virtual en la clase
base. Todas las funciones de las clases derivadas que encajen con la declaración que esté en
la clase base serán llamadas usando el mecanismo virtual. Se puede usar la palabra
reservada virtual en las declaraciones de las clases derivadas (no hace ningún mal), pero
es redundante y puede causar confusión.
Para conseguir el comportamiento deseado de Instrument2.cpp, simplemente hay que
añadir la palabra reservada virtual en la clase base antes de play ().
//: C15:Instrument3.cpp
// Late binding with the virtual keyword
#include <iostream>
using namespace std;
enum note { middleC, Csharp, Cflat }; // Etc.
class Instrument {
public:
virtual void play(note) const {
cout << "Instrument::play" << endl;
}
};
// Wind objects are Instruments
// because they have the same interface:
class Wind : public Instrument {
public:
// Override interface function:
void play(note) const {
cout << "Wind::play" << endl;
}
};
void tune(Instrument& i) {
// ...
i.play(middleC);
}
4
int main() {
Wind flute;
tune(flute); // Upcasting
} ///:~
2. CLASES ABSTRACTAS
Una clase que declara la existencia de métodos pero no la implementación de dichos
métodos (o sea, las llaves { } y las sentencias entre ellas), se considera una clase abstracta.
Una clase abstracta puede contener métodos no-abstractos pero al menos uno de los
métodos debe ser declarado abstracto.
Para declarar una clase o un metodo como abstractos, se utiliza la palabra reservada
abstract.
abstract class Drawing
{
abstract void miMetodo(int var1, int var2);
String miOtroMetodo( ){ ... }
}
Una clase abstracta no se puede instanciar pero si se puede heredar y las clases hijas serán
las encargadas de agregar la funcionalidad a los métodos abstractos. Si no lo hacen así, las
clases hijas deben ser también abstractas.
Reglas de uso:
Una clase abstracta solo puede ser usada como clase base para otras clases,
pero no puede ser instanciada para crear un objeto.
Una clase abstracta no puede ser utilizada como argumento o como retorno de una
función.
Si puede declararse punteros-a-clase abstracta.
Se permiten referencias-a-clase abstracta, suponiendo que el objeto temporal no es
necesario en la inicialización.
Las clases abstractas actúan como expresiones de conceptos generales de los que pueden
derivarse clases más concretas. No se puede crear un objeto de un tipo de clase abstracta,
aunque se pueden utilizar punteros y referencias a los tipos de clase abstracta.
Una clase que contiene al menos una función pura virtual se considera una clase
abstracta. Las clases derivadas de la clase abstracta deben implementar la función virtual
pura o deben ser también clases abstractas.
5
Una función virtual se declara como "pura" mediante la sintaxis de pure-specifier (descrita
en Implementación de protocolo de clase).
Abstracción:
Es la ocultación de detalles irrelevantes o que no se desean mostrar. Podemos distinguir en
una clase dos aspectos desde el punto de vista de la abstracción:
Interfaz: lo que se puede ver/usar externamente de un objeto.
Implementación: cómo lleva a cabo su cometido.
Resumiendo: nos interesa saber qué nos ofrece un objeto, pero no cómo lo lleva a cabo.
Restricciones de acceso en C++
En C++ se puede especificar el acceso a los miembros de una clase utilizando los siguientes
especificadores de acceso:
public: Interfaz de la clase.
private: Implementación de la clase.
protected: Implementación de la familia.
Estos especificadores no modifican ni la forma de acceso ni el comportamiento, únicamente
controlan desde dónde se pueden usar los miembros de la clase:
public: desde cualquier sitio.
private: desde los métodos de la clase.
protected: desde los métodos de la clase y desde los métodos de las clases
derivadas.
3. POLIMORFISMO
El Polimorfismo (implementado en C++ con funciones virtuales) es la tercera
característica esencial de un lenguaje orientado a objetos, después de la abstracción de
datos y la herencia.
De hecho, nos provee de otra dimensión para la separación entre interfaz y la
implementación, desacoplando el qué del cómo. El Polimorfismo permite mejorar la
organización del código y su legibilidad así como la creación de programas extensibles que
pueden "crecer" no sólo durante el desarrollo del proyecto, si no también cuando se deseen
nuevas características.
La encapsulación crea nuevos tipos de datos combinando características y
comportamientos. El control de acceso separa la interfaz de la implementación haciendo
privados (private) los detalles. Estos tipos de organización son fácilmente entendibles por
6
cualquiera que venga de la programación procedimental. Pero las funciones virtuales tratan
de desunir en términos de tipos. En el Capítulo 14, usted vio como la herencia permitía
tratar a un objeto como su propio tipo o como a su tipo base. Esta habilidad es básica
debido a que permite a diferentes tipos (derivados del mismo tipo base) ser tratados como si
fueran un único tipo, y un único trozo de código es capaz de trabajar indistintamente con
todos. Las funciones virtuales permiten a un tipo expresar sus diferencias con respecto a
otro similar si ambos han sido derivados del mismo tipo base. Esta distinción se consigue
modificando las conductas de las funciones a las que se puede llamar a través de la clase
base.
Clasificación
Se puede clasificar el polimorfismo en dos grandes clases:
Polimorfismo dinámico (o polimorfismo paramétrico) es aquél en el que el
código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que
se trabaja. Así, puede ser utilizado a todo tipo de datos compatible.
Polimorfismo estático (o polimorfismo ad hoc) es aquél en el que los tipos a los
que se aplica el polimorfismo deben ser explícitos y declarados uno por uno antes
de poder ser utilizados.
Diferencias entre polimorfismo y sobrecarga
El polimorfismo, suele ser bastante ventajoso aplicado desde las interfaces, ya que
permite crear nuevos tipos sin necesidad de tocar las clases ya existentes
(imaginemos que deseamos añadir una clase Multiplicar), basta con recompilar todo
el código que incluye los nuevos tipos añadidos. Si se hubiera recurrido a la
sobrecarga durante el diseño exigiría retocar la clase anteriormente creada al añadir
la nueva operación Multiplicar, lo que además podría suponer revisar todo el código
donde se instancia a la clase.
La sobrecarga se da siempre dentro de una sola clase, mientras que el polimorfismo
se da entre clases distintas.
Un método está sobrecargado si dentro de una clase existen dos o
más declaraciones de dicho método con el mismo nombre pero con parámetros
distintos, por lo que no hay que confundirlo con polimorfismo.
En definitiva: La sobrecarga se resuelve en tiempo de compilación utilizando los
nombres de los métodos y los tipos de sus parámetros; el polimorfismo se resuelve
en tiempo de ejecución del programa, esto es, mientras se ejecuta, en función de que
clase pertenece un objeto.
Ejercicio
Implementacón de un programa cuya jerarquía sea al menos de ocho clases y que use
polimorfismo en lenguaje C++.
7
#include"circulo.h"
#include"cuadrado.h"
#include"rectangulo.h"
#include"triangulo.h"
#include"trapecio.h"
main()
{
Una_dimension obj5;
doble_dimension obj6;
triple_dimension obj7;
circulo obj;
cuadrado obj2;
Una_dimension *obj1=&obj;
Una_dimension *obj3=&obj2;
obj1->mostrar();
obj3->mostrar();
rectangulo obj4;
doble_dimension *obj8=&obj4;
obj8->mostrar();
getch();
triangulo obj9;
trapecio obj11;
doble_dimension *obj10=&obj9;
8
doble_dimension *obj12=&obj11;
obj10->mostrar();
obj12->mostrar();
}
#ifndef CIRCULO_H
#define CIRCULO_H
#include <Una_dimension.h>
class circulo: public Una_dimension
{
public:
circulo();
virtual ~circulo();
double getPerimetro();
double getSuperficie();
void mostrar();
protected:
private:
};
#endif // CIRCULO_H
#ifndef CUADRADO_H
#define CUADRADO_H
#include <Una_dimension.h>
class cuadrado:public Una_dimension
9
{
public:
cuadrado();
virtual ~cuadrado();
double getPerimetro();
double getSuperficie();
void mostrar();
protected:
private:
};
#endif // CUADRADO_H
#ifndef DOBLE_DIMENSION_H
#define DOBLE_DIMENSION_H
#include <Una_dimension.h>
class doble_dimension:public Una_dimension
{
public:
doble_dimension();
virtual ~doble_dimension();
double getDimension2();
void setDimension2(double dimension);
protected:
double dimension2;
10
private:
};
#endif // DOBLE_DIMENSION_H
#ifndef RECTANGULO_H
#define RECTANGULO_H
#include<doble_dimension.h>
class rectangulo:public doble_dimension
{
public:
rectangulo();
virtual ~rectangulo();
double getPerimetro();
double getSuperficie();
void mostrar();
protected:
private:
};
#endif // RECTANGULO_H
#ifndef TRAPECIO_H
#define TRAPECIO_H
#include<triple_dimension.h>
class trapecio:public triple_dimension
11
{
public:
trapecio();
virtual ~trapecio();
double getPerimetro();
double getSuperficie();
double lado();
void mostrar();
protected:
private:
};
#endif // TRAPECIO_H
#ifndef TRIANGULO_H
#define TRIANGULO_H
#include<triple_dimension.h>
class triangulo:public triple_dimension
{
public:
triangulo();
virtual ~triangulo();
double getPerimetro();
double getSuperficie();
void mostrar();
protected:
12
private:
};
#endif // TRIANGULO_H
#ifndef TRIPLE_DIMENSION_H
#define TRIPLE_DIMENSION_H
#include<doble_dimension.h>
#include<math.h>
class triple_dimension:public doble_dimension
{
public:
triple_dimension();
virtual ~triple_dimension();
double getDimension3();
void setDimension3(double dimension);
protected:
double dimension3;
private:
};
#endif // TRIPLE_DIMENSION_H
#ifndef UNA_DIMENSION_H
#define UNA_DIMENSION_H
#include<iostream>
#include<conio.h>
using namespace std;
13
class Una_dimension
{
public:
Una_dimension();
virtual ~Una_dimension();
double getDimension1();
void setDimension1(double dimension);
double dimension1;
virtual void mostrar();
protected:
private:
};
Evaluación de resultados
14
CONCLUCIONES
Las funciones virtuales se caracterizan por añadir una mayor cantidad de trabajo
computacional y que, por tanto, es recomendable utilizar las prestaciones del polimorfismo,
esto es, poner la palabra clave virtual a una función, sólo cuando estemos seguros de que
esa función va a ser redefinida.
Tampoco se consume mucho tiempo y se sobrecargue todo en exceso pero suele ser una
práctica común entre los que comienzan a trabajar más o menos en serio con el C++
utilizar prestaciones de la POO cuando no son necesarias.
El polimorfismo indica que una variable pasada esperada puede adoptar múltiples formas.
BIBLIOGRAFÍA o http://profesores.fi-b.unam.mx/carlos/java/java_basico3_5.html
o http://arco.esi.uclm.es/~david.villa/pensar_en_C++/vol1/ch15s04.html
o http://c.conclase.net/curso/?cap=037