Genericidad 1. Funciones genéricas 2. Clases genéricas Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas.
Genericidad Re-utilización del código: Uno de los problemas: tipos de datos. class A; { int x; int operator>(a a) {return( x>a.x? 1:0); // máximo de dos objetos de la clase A A maximo(a a,a b) { return( a>b? a : b); // máximo de dos números float float maximo(float a,float b) { return( a>b? a : b); Ambas funciones son prácticamente iguales: sólo cambian en los tipos de datos. Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 109
Genericidad En C++, para utilizar tipos genéricos de datos: uso de plantillas (templates): funciones genéricas. clases genéricas. Funciones genéricas: T maximo(t a,t b) { return( a>b? a : b); void main(void) { A a,b,c; int x,y,z; c=maximo(a,b); z=maximo(x,y); -Se utiliza la misma función. -El compilador genera el código necesario a partir de las plantillas que ha guardado internamente. -Es una forma de poliformismo: número infinito de potenciales sobrecargas de una función. Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 110
Funciones genéricas Uso de funciones genéricas: T min(const T a,const T b) { return( a<b? a : b); void main(void) { int x,y,z; float f; void *u,*v,*w; z=min(x,y); // correcto. u=min(x,y); // correcto, aunque puede haber // un error en tiempo de // ejecución. Sólo se mira el // tipo de los parámetros. u=min(v,w); // correcto, devuelve la // dirección más pequeña. z=min(x,f); // incorrecto: los parámetros // x,f no son del mismo tipo. Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 111
Sobrecarga de funciones genéricas Se pueden sobrecargar de la misma forma que los otros tipos de funciones. T min(t a,t b) { return( a<b? a : b); template <class T1,class T2> T1 min(t1 a,t2 b) { <class T> T min(int a,t b) { <class T> // incorrecto T min(int a,int b) // alguno de los { return( a<b? a : b); // parámetros // tiene que ser // genérico Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 112
Especialización de funciones genéricas Cuando definimos una función genérica: especificamos un tratamiento para todos los tipos de datos. a veces, se precisa un tratamiento específico para algún tipo de dato en concreto. Ejemplo: Dada la anterior función genérica maximo(): char n1[30]= Hola ; char n2[30]= Saludos ; maximo(n1,n2); Especialización (sobrecarga): Esta llamada funcionaría, pero no haría lo que esperaríamos. const char maximo(const char *s1, const char *s2) { return( strcmp(s1,s2)? s1 : s2 ); Se busca primero si hay una función especializada, y si no se encuentra, se busca una genérica. Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 113
Patrones para definiciones genéricas de clases. Durante la compilación se expanden para definir completamente clases. Ejemplo de definición: class vector { T *v; int tam; vector(int); T & operator[] (int); ; // instanciación de clases genéricas, // cuando se declaran objetos vector<int> vi(10); //vector de 10 int vector<char> vc(50); //vector de 50 char vector<double> vd(3); //vector de 3 doubles Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 114
Definición de métodos en clases genéricas: class vector { T *v; int tam; vector(int); T & operator[] (int); ; vector<t>::vector(int size) { tam=size; v=new T[tam]; T & vector<t>::operator[] (int i) { return(v[i]); void main(void) { vector<double> d(30); vector<char> *p=new vector<char>(50); Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 115
Especialización de métodos en clases genéricas: Para ciertos tipos, las clases genéricas no se comportan como esperaríamos. Añadir declaraciones explícitas de métodos especializados. Ejemplo: class pila { int tam; T* buffer; int cabeza; Pila(int size); ~Pila(); int Vacia(void); int Llena(void); int Push(T d); T Pop(void); ; Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 116
int pila<t>::push(t d) { if(llena()) return -1; else { buffer[cabeza]=d; cabeza++; return 0; // Especialización del método Push() int pila<char *>::Push(char * cad) { char *copia; if(llena()) return -1; else { copia=new char[strlen(cad)+1]; strcpy(copia,cad); buffer[cabeza]=copia; cabeza++; return 0; Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 117
Tipos de parámetros formales: Tipos genéricos. Parámetros constantes. Genericidad con parámetros constantes: template <int TAM, class T> class vector { T vect[tam]; T & operator[] (int i); ; TAM debe ser una constante conocida en tiempo de compilación template <int TAM, class T> T & vector<tam,t>::operator[](int i) { if(i<tam && i>=0) return(vect[i]); else exit(-1); Instanciación de objetos void main(void) { vector<30,int> vi; Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 118
Clases anidadas: Las clases genéricas no se pueden anidar. Una clase genérica puede contener la definición de una clase no genérica. Herencia en clases genéricas: Se pueden derivar clases genéricas de otras clases genéricas: template <class T,int TAM> class pila { T buffer[tam]; int cabeza; void Push(T a); ; template <class T,int TAM> class doble_pila: public pila<t,tam> { void Push2(T a); ; Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 119
Herencia en clases genéricas (continuación): Se puede derivar una clase no genérica de una genérica: //clase genérica template <class T,int TAM> class pila { T buffer[tam]; int cabeza; void Push(T a); ; //clase no genérica derivada de genérica class monton: public pila<int,5> { // Aquí se hereda lo de la clase pila // de enteros y de tamaño 5. ; Lenguaje C++. Leng. Prog. II. Filiberto Pla y Jorge Badenas. 120