Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206)...

23
Plantillas Programación genérica Pablo San Segundo (C-206) [email protected]

Transcript of Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206)...

Page 1: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Plantillas

Programación genérica Pablo San Segundo (C-206)

[email protected]

Page 2: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Índice

Nociones generales Plantillas para funciones Plantillas para clases

Page 3: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Nociones generales de plantillas Mecanismo mediante el cual un tipo puede ser usado como

parámetro en la definición de una clase o función: GENERALIZACIÓN

Se pueden generalizar tipos de datos base o de usuario La instanciación concreta de la plantilla con un tipo concreto se

denomina especialización Puede verse como un polimorfismo de tipo (ver tema anterior)

pero en tiempo de compilación

Ejemplo de prototipo de plantilla de FUNCIÓN

template <class T> void foo (T& ref);

Ejemplo de plantilla de CLASE template <class T> class C{ public: T atributo; };

Ejemplo de definición de una plantilla de FUNCIÓN (*.cpp)

template <class T> T min(T a, T b){ return (a<b)? a:b; }

Page 4: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

PLANTILLAS PARA FUNCIONES

Page 5: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Consideraciones generales

La especialización de la plantilla de función se produce en tiempo de compilación, en la instrucción de llamada Si no se llama a la función, no se incorpora al binario el código

de la plantilla Pueden tener múltiples parámetros <class T, class U, …>

template <class T> T min(T a, T b){ return (a<b)? a:b; } void main(){ float a=3.18, b=4.7; cout<<min(a,b)<<endl; //o min<float>(a, b) }

Instanciación por el compilador en la llamada

CUESTIÓN Implemente una plantilla de función que intercambie los valores de dos tipos base cualesquiera

template <class T> void swap(T& a, T& b){ T temp = a; a=b; b=temp; }

Page 6: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Sintaxis

Identificadores de tipo (p.ej. ‘T’), precedidos de la palabra clave class ó typename

template <class T, class U> void foo( T&, U&, int n=10 );

template <class T, class U, int n > void foo(T&, U& );

Tipos base: especialización siempre como constante

Parámetros múltiples

template <class | typename <id> [,…]> <tipo de retorno> <identificador> (<lista de parametros>) ;

Page 7: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Ejemplo I

template <class T, int n> void foo(T& ref ){ cout<<"el argumento es:"<<ref+n<<endl; } template <class T> void foo(T& ref, int n ){ cout<<"el argumento es:"<<ref+n<<endl; }

CUESTION Indique cuales de estos casos de uso de las funciones genéricas son correctos:

void main(){ int k=0; foo<int, 3>(k); //A foo<int>(k,3); //B foo(k,3); //C foo(k); //D }

Page 8: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Ejemplo II: Especialización

template <class T> bool isEqual(T a, T b){ return (a==b)? 1:0; } void main(){ double a=3.18, b=3.19; if(isEqual(a,b)) cout<<"son iguales"<<endl; }

bool isEqual(double a, double b){ return (abs(a-b)<=0.1)? 1:0; }

CUESTION I. Especialice la función genérica isEqual para que defina la relación de igualdad para números en coma flotante de doble precisión con una tolerancia de 0,1. II. Compruebe su correcto funcionamiento.

Page 9: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Consideraciones para el compilador La definición y declaración de una plantilla genérica pueden ir

separadas en fichero de cabecera (.h) y fichero fuente (.cpp). Sin embargo, el compilador necesita conocer la definición de la

plantilla para especializarla. Si se pretende especializar una función en un fichero fuente distinto

a donde está definida, lo más simple es incluir la definición de la plantilla en el propio fichero de encabezado Fichero: plantilla.h inline template <class T> bool isEqual(T a, T b){ return (a==b)? 1:0; }

#include "plantilla.h" void main(){ double a=3.18, b=4.7; if(isEqual(a,b)) cout<<"son iguales"<<endl; }

Si la definición de isEqual se encuentra en plantilla.cpp no puede enlazar

Page 10: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Otras consideraciones

Una especialización manual de una plantilla función es una definición de función ordinaria

Es posible sobrecargar las plantillas de funciones mediante el mecanismo habitual de tipo

Pueden ser métodos de clases

Fichero: punto.h class Punto{ double x; double y; public: Punto(double x, double y):x(x), y(y){} void print(){ cout<<"x:"<<x<<","<<"y:"<<y<<endl; } template <class U> void print() { cout<<"x:"<<(U)x<<","<<"y:"<<(U)y<<endl; } };

Page 11: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

PLANTILLAS PARA CLASES

Page 12: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Generalidades

Generalización extendida al caso de clases EJERCICIO Implemente una clase Punto genérica para 2D y cualquier tipo base numérico de coordenadas. Incluya un constructor apropiado y una función que muestre en pantalla ambas coordenadas

Declaración (punto.h) template <class T> class Punto { T x, y; public: Punto(T x, T y); void print(){cout<<“(“<<x<<“:”<<y<<“)”<<endl;} };

Definición del constructor (punto.cpp) template <class T> Punto<T>::Punto(T x, T y){ this->x=x; this->y=y; } Test unitario(main.cpp)

void main(){ Punto<int> miPunto(10, 20); miPunto.print(); }

Sintaxis obligatoria

Page 13: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Aspectos de compilación En principio NO es posible pasar al usuario de una plantilla de clase

solamente el fichero cabecera con la declaración de la clase genérica (y el fuente precompilado)

Es necesario conocer también las definiciones/especializaciones del tipo para que el compilador pueda instanciar la clase.

Soluciones: A. Las definiciones se colocan en el fichero de cabecera B. Se coloca una declaración de especialización genérica en el fichero fuente para

cada función miembro específica que va a ser instanciada

Fichero cabecera (punto.h) template<class T>class Punto{ T x;T y; public: Punto(T x, T y); void print(){cout<<x<<“:”<<y<<endl;} };

Fichero de definición (punto.cpp) template <class T> Punto<T>::Punto(T x, T y){ this->x = x; this->y = y; } //declaración de especialización template Punto<int>::Punto(int, int);

Test Unitario (main.cpp) #include “punto.h” void main(){ Punto<int> miPunto(10, 20); miPunto.print(); }

Page 14: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Otras consideraciones generales No es posible sobrecargar una plantilla de clase Parámetros múltiples posibles Parámetros de tipo base (parámetros de expresión) Pueden usarse tantos como se quiera y aparecer en cualquier lugar

de la declaración de la clase siempre que se puedan sustituir por una constante

template<typename T, int n> class Array { //… };

Page 15: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Ejercicio

EJERCICIO Implemente una clase genérica Array con parámetros tipo de datos y número de elementos (incluya métodos públicos push_back y print). Programe un caso de uso de prueba.

template<class T, int n> class Array { T x[n]; int nElem; public: Array(){nElem =0;} void push_back(int dato){ if(nElem <n){ x[nElem++]=dato; } } ostream& print(ostream & o =cout){ for (int i=0; i<nElem; i++){ o<<x[i]<<" "; } o<<endl; return o; } };

Page 16: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Especialización de funciones miembro

template <class type_t, int N> class ARRAY{ //… public: ostream& print(ostream& o=cout); }; template <> ostream& ARRAY<int, 3>::print(ostream& o){ for (int i=0; i<l.size(); i++){ o<<l[i]<<" "; } o<<endl; return o; }

Page 17: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Funciones miembro como plantilla

template <class type_t, int N> class ARRAY{ //… public: template<class U> ostream& print(ostream& o=cout); }; template <class type_t, int N> template<class U> ostream& ARRAY<type_t, N>::print(ostream& o){ for (int i=0; i<l.size(); i++){ o<<static_cast<U>(l[i])<<" "; } o<<endl; return o; }

Page 18: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Ejercicio: plantillas + herencia

EJERCICIO Generalice la implementación de la jerarquía vista para gestionar de manera cómoda diferentes implementaciones de la serie Fibonacci al caso de una función con 2 argumentos genéricos y que devuelva un tercero

<<interface>> IAlg

+ virtual ret_t solve(p1_t, p2_t)=0

Alg_B

+ ret_t solve(p1_t,p2_t)

Alg

-IAlg* +solve(p1_t, p2_t)

Alg_A

+ ret_t solve(p1_t,p2_t)

Page 19: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Clases de la librería estándar para colecciones (STL)

Cadenas de caracteres string

Colecciones (iterables) vector: elementos en posiciones consecutivas en memoria

acceso eficiente

list : lista de elementos enlazados borrado e inserción eficiente

set : colección de elementos distintos en estricto orden de precedencia

map: diccionario de elementos (asociación llavedato) Acceso a través de la llave Elementos ordenados por estricto orden de precedencia

Page 20: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

String

#include <string>

typedef basic_string<char> string

void main(){ string str("un saludo"); str+= " a todos"; cout<<str<<endl; str.append(" los alumnos en clase"); cout<<str<<endl; str.insert(9," muy efusivo"); cout<<str<<endl; }

Sobrecarga del operador texto para la clase string como función independiente

Sobrecarga del operador suma para concatenar cadenas

Page 21: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Vector

#include <vector>

template <class T, class Allocator = allocator<T> > class vector

void main(){ vector<int> v(NUM_ELEM); cout<<"La capacidad actual es: "<<v.size(); for(int i=0; i<NUM_ELEM; i++){ v[i]=i; } cout<<endl; //añadir elementos al final (amplían la capacidad actual) v.push_back(100); for(int i=0; i<v.size(); i++){ cout<<v[i]<<" "; } cout<<endl; //borrado de elementos de la colección //último v.pop_back(); for(int i=0; i<v.size(); i++){ cout<<v[i]<<" "; } cout<<endl; //eliminar elemento en la posición i-ésima int i=5; v.erase(v.begin()+(i-1)); for(int i=0; i<v.size(); i++){ cout<<v[i]<<" "; } cout<<endl;

}

sobrecarga del operador [ ] (acceso aleatorio)

Page 22: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Ejercicio de algoritmia con la STL

Para un clase que encapsule un punto 2D Cree una colección de puntos Cree un vector (STL) de punteros a los elementos de dicha

colección Manipule dicho vector de diferentes formas

Ordene el vector por algún criterio Encuentre un punto en la colección Imprima el vector de diferentes maneras Borre el vector Etc…

Page 23: Plantillas Programación genérica · Plantillas Programación genérica Pablo San Segundo (C-206) pablo.sansegundo@upm.es

Resumen I. Concepto de programación genérica II. Funciones con plantillas, especialización III. Clases con plantillas, especialización IV. Casos prácticos

¿PREGUNTAS?