Tipos - Oldemar Rodríguez Rojas

Anuncio
Programación C++
Tipos Parametrizados
Dr. Oldemar Rodríguez Rojas
Escuela de Informática
Universidad Nacional
Tipos (clases) parametrizados
“Templates”
La noción de "templates" provee los
llamados
algunas
veces
Tipos
Parametrizados o Genéricos.
Para esto se reincorporan en C++
conceptos que estaban presentes en
lenguajes como Clu y Ada. [Stroustrup-2]
¿Para qué sirven los tipos parámetrizados?
Es muy común en programación implementar una misma
estructura de datos varias veces, esto debido a que el
tipo del nodo es diferente.
Por ejemplo, implementar una lista de Personas y luego
implementar una una lista de Libros ambas con los
mismos algoritmos.
evitar esta redundancia de código, Bjarne
Stroustrup introduce en C++ la idea de que una clase
pueda recibir un tipo o varios tipos como parámetro.
Para
Sintaxis los tipos parámetrizados
Antes
de
presentar
la
nueva
implementación de la lista de “Personas”,
dedicaremos esta sección a explicar con
detalle la sintaxis y la semántica de los
tipos parametrizados.
Para ilustrar este nuevo concepto
implementaremos una Pila Parametrizada
mediante un arreglo.
Plantillas
Cuando se crea una función o una
clase, se debe especificar el tipo de
dato que recibe como parámetros y los
que retorna, esto para el caso de las
funciones, y los tipos de datos que
contiene la clase como atributos y los
tipos de datos con que operan sus
métodos.
Plantillas
Cuando se desea ingresar un tipo de dato con el
cual no fue definida la función o clase, se debe
sobrescribir para poder operar sobre esta, esto
implica una definición diferente por cada tipo de
dato. Esto se hace difícil de mantener en la
práctica, pues si se desea hacer un corrección, o
incluir alguna mejora se debe hacer sobre la
totalidad de las definiciones, además que el
código sería muy largo y difícil de mantener.
Plantillas
Las plantillas (templates) resuelven
este problema, estas nos permiten
parametrizar estas clases o funciones
para adaptarlas a cualquier tipo de dato.
Tipos parametrizables
Las plantillas nos permiten decirle al
compilador que haga el trabajo pesado
por nosotros, y que sea el quien genere
una declaración de una función o clase
para que estas puedan operar o tratar
con un tipo de dato en concreto, sin
nosotros entrar a implementar una
declaración por cada tipo existente.
Cómo crear una plantilla?
C++ permite crear plantillas de funciones y plantillas
de clases.
La palabra clave “template” es utilizada al principio
de cada declaración y definición de una clase o
función plantilla.
Los parámetros de la plantilla se escriben dentro
de los operadores “<>”, estos corresponden a las
cosas que pueden cambiar con cada instancia.
Clases Plantilla
La sintaxis para declarar una clase plantilla
es parecida a la de cualquier otra clase,
pero nuevamente se debe añadir al
principio una presentación de la clase que
se usará como referencia en la plantilla:
template<class id>
class nombreClase
{
// Declaración de funciones
// y datos miembro de la plantilla
};
template <class TIPO>
class Pila {
TIPO* Datos;
int Top;
public:
Pila() {
Datos = new TIPO[MAX];
Top = VACIO;
}
~Pila() {delete [] Datos; }
void Insertar(TIPO c);
TIPO Sacar();
bool Vacia();
bool Llena();
};
UNA PILA
PARAMETRIZADA
VER <EJ1.CPP>
Compatibilidad entre tipos
parametrizados
La
compatibilidad
entre
tipos
parametrizados no es tan clara como en
los tipos usuales de C++, debido a que
el compilador de C++ no puede hacer
una conversión automática de tipos.
Suponga que en el ejemplo anterior
cambiamos el programa principal por el
siguiente:
int main() {
Pila<int> x_int1;
x_int1.Insertar(1);
x_int1.Insertar(2);
Pila<int> x_int2;
x_int2.Insertar(3);
x_int2.Insertar(-2);
Pila<float> x_float;
x_float.Insertar(1.3);
x_float.Insertar(5.1);
x_int1=x_int2;
x_int1=x_float;
// Esta línea genera
// error
return 0;
}
En el anterior fragmento de
código se declaran tres pilas: dos
pilas de tipo entero y la tercera
de tipo flotante. La última línea
de este programa genera error
debido a que C++ no puede
convertir en forma automática la
pila de flotantes en una pila de
enteros. Es posible asignar una
pila de enteros a otra pila de
enteros, como se hace con la
instrucción:
x_int1=x_int2;
Los argumentos en clases
parametrizadas
Los argumentos de un tipo (clase) parametrizado no están
restringidos a clases, aunque esto es lo más común. Los
parámetros de un tipo parametrizado pueden ser enteros, flotantes,
nombres de funciones o incluso expresiones constantes.
Por ejemplo en el siguiente fragmento de código se define una
clase parametrizada Vector, en la que son parámetro el tipo de la
pila y el tamaño del arreglo que almacenará el vector.
template <class TIPO, int n>
class Vector {
TIPO Datos[n];
.........
}
Dos instancias de clase son compatibles si sus
argumentos en el parámetro TIPO son los mismos y si
sus argumentos en n tienen el mismo valor, por ejemplo
las siguientes instancias son compatibles:
Vector<float,100> V1;
Vector<float, 2*50> V2;
En el siguiente ejemplo mejoramos la implementación
de la pila del ejemplo anterior, para esto incorporamos
un nuevo parámetro para el tamaño máximo de la pila.
template <class TIPO, int Max>
class Pila {
TIPO* Datos;
int Top;
public:
Pila() {
Datos = new TIPO[Max];
Top = VACIO;
}
~Pila() {delete [] Datos; }
void Insertar(TIPO c);
TIPO Sacar();
bool Vacia();
bool Llena();
};
template <class TIPO,int Max>
void Pila<TIPO,Max>::Insertar(TIPO c)
{
Datos[++Top] = c;
}
template <class TIPO,int Max>
TIPO Pila<TIPO,Max>::Sacar() {
return (Datos[Top--]);
}
template <class TIPO,int Max>
bool Pila<TIPO,Max>::Vacia() {
return (Top==VACIO);
}
template <class TIPO,int Max>
bool Pila<TIPO,Max>::Llena() {
return (Top==Max-1);
}
Funciones con tipo parametrizado
Además de clases parametrizadas, C++ permite definir
funciones con tipo parametrizado de manera muy similar.
Una función parametrizada (template function) define en
realidad una familia de funciones; cada una con un tipo
particular, los parámetros con que la función es invocada
determinan cual versión de la función será ejecutada.
En el siguiente fragmento de código se presenta una
función parametrizada que calcula el mínimo entre dos
elementos cuyo tipo es desconocido cuando la función es
implementada.
include <iostream> // VER <EJ2.CPP>
using std::endl;
using std::cin;
using std::cout;
template<class TIPO> TIPO Min(TIPO a, TIPO b) {
if(a<b)
return a;
else
return b;
}
int main() {
char Ch1='O', Ch2='F', Res;
int N1=100, N2=200, R;
Res=Min(Ch1,Ch2);
cout << " El caracter menor es: " << Res;
R=Min(N1,N2);
cout << "\n El entero menor es " << R;
cout << "\n Fin \n";
system("pause");
system("cls");
return 0;
}
¿Cuál es la diferencia entre tipos parametrizados y
polimorfismo? ¿Puede uno sustituir al otro? ¿Cuál
concepto es mejor o más potente?
Las principales diferencias en C++ entre una función
polimórfica y una función parametrizada son las siguientes:
1. Las funciones parametrizadas pueden trabajar con
tipos aritméticos.
2. Las funciones polimórficas deben usar punteros.
3. La generalidad del polimorfismo se restringe a una
jerarquía de clases.
4. La generalidad de las funciones parametrizadas es
ilimitada.
5. Las funciones parametrizadas tienden a generar un
archivo ejecutable más grande.
La STL - “Standard Template Library”
El mes de abril de 1995, los comités ANSI e ISO C++
publicaron su primer documento oficial, el Committe Draft
(CD) para estudio y revisión de la comunidad de desarrollo
informática internacional.
La biblioteca C++ Standard, conocida como Standard
Template Library (STL) es una biblioteca que incluye clases
contenedoras y algoritmos basados en plantillas. STL es
una biblioteca muy importante para el desarrollo de
programas
profesionales
dado
que
facilitará
considerablemente el diseño y construcción de aplicaciones
basadas en estructuras de datos tales como vectores, listas,
conjuntos y algoritmos.
La librería estándar de plantillas
(STL -The Standard Template Library)
1
• STL proporciona un conjunto de estructuras de datos y de
algoritmos que operan sobre aquéllas.
2
• Es un entorno conceptual que facilita a los usuarios la adición de
sus propios algoritmos y estructuras de datos.
3
• Los nuevos algoritmos funcionarán con todas las estructuras de
datos (contenedores) existentes, a la vez que sobre las nuevas
estructuras de datos se podrán aplicar todos los algoritmos
existentes
Algoritmo
• Define el procedimiento computacional
Contenedor
• Gestiona un conjunto de localizaciones
en memoria
Iterador
• Provee un medio para que un algoritmo
recorra un contenedor
ObjetoFunción
• Objeto reutilizable por otros
componentes
Adaptador
• Adapta un componente a una interfaz
distinta
La librería estándar de plantillas
(STL -The Standard Template Library)
El núcleo de la STL son los algoritmos, que
utilizan iteradores para acceder a contenedores.
Características:
proveen un fuerte chequeo de tipos
sus iteradores son generalizaciones de los punteros
permiten el uso en algoritmos, de funciones
encapsuladas en objetos
los componentes de la STL son al menos tan
eficientes como los codificados a mano
Contenedores
Es un objeto que contiene otros objetos.
Estos contenedores son implementados como
clases plantillas, que permiten gran flexibilidad en
los tipos soportados por los elementos.
Un contenedor maneja los espacios de
almacenamientos para sus elementos, y provee
funciones miembro para el acceso a estos
directamente o a través de los iteradores (objetos
de referencia que tienen un comportamiento similar
a los punteros)
Categorías de contenedores
Secuencial
• Almacenamiento de ítems es lineal, con
inserciones rápidas al final
• Vector
Asociativo
• Para búsquedas asociativas rápidas
• Conjuntos
Adaptador
• Interfaces a otros tipos de colecciones
• Colas, pilas
Contenedores secuenciales
Estas clases son diseñadas para brindar
acceso secuencial y aleatorio a sus
miembros o elementos.
Provee un acceso secuencial eficiente a la
lista de objetos que contiene. La librería
estándar de C++ provee tres tipos
diferentes de contenedores de este tipo:
Vector
List
Deque (Doble vector, inserción adelante y
atrás)
Contenedores asociativos
Son contenedores optimizados para tener
acceso a sus elementos mediante valores
claves. Son optimizados internamente
C++ provee cuatro tipos diferentes de
contenedores de este tipo:
Map
Multimap
Set
Multiset
Contenedores adaptadores
Los adaptadores son en esencia, plantillas
que procuran un interfaz especial para los
otros tipos de contenedores. Los
adaptadores “adaptan” o “adecúan” un
determinado contenedor para que adopte
un nuevo comportamiento, restringiendo
ciertas características y cambiando otras.
Stack
queue
priority_queue
¿Qué es un Iterador?
1
2
3
• Un iterador es algo que permite un conjunto de operaciones
en una estructura de datos sin tener en cuenta los tipos de
datos o la naturaleza de tal estructura.
• Un iterador es un mediador independiente entre los datos y el
algoritmo o proceso a realizar sobre estos.
• Un iterador es un objeto que permite recorrer los elementos
de una colección, recorriéndola (o “atravesándola”) con
distintas estrategias, para cada estrategia quizás haya que
procurar un iterador distinto.
#include <iostream>
#include <vector>
using namespace std;
Ejemplo de
Iterator: ver
<Ej2-1.cpp>
int main ()
{
vector<int> myvector;
for (int i=1; i<=5; i++)
myvector.push_back(i);
vector<int>::iterator it;
cout << "myvector contains:";
for(it=myvector.begin();it<myvector.end();it++)
cout << " " << *it;
cout << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
Ejemplo de
Iterator Reverso:
ver <Ej2-2.cpp>
int main ()
{
vector<int> myvector;
for (int i=1; i<=5; i++)
myvector.push_back(i);
cout << "myvector contains:";
vector<int>::reverse_iterator rit;
for (rit=myvector.rbegin();rit<myvector.rend();++rit )
cout << " " << *rit;
cout << endl;
return 0;
}
Algoritmos
Cada contenedor define operaciones para manipular así
mismo y a sus elementos, implementar todas estas
operaciones por cuenta propia, puede ser muy
engorroso y posiblemente se comentan errores en el
proceso. Debido a que casi todas estas operaciones son
similares para cualquier tipo de elementos almacenados,
un conjunto de algoritmos genéricos ya incluidos en STL
pueden ser utilizados directamente.
Algunos de los algoritmos más comúnmente utilizados:
Ejemplo: Uso de la clase list
Ver <EJ3.CPP>
Lista de Personas
mediante la
reutilización de la clase
list
Ver <Ej4.cpp>
Tarea:
Estudiar todos los Ejemplos del Capítulo
22 del libro C++ Cómo Programar de
Deitel y entregarlos en un CD con los
respectivos proyectos en Visual C++ y
con todos los comentarios en español.
MUCHAS GRACIAS….
Descargar