Gracias a c++ podemos definir clases-plantilla: son clases PARAMETRIZABLES por lo general entidades abstractas que se pueden concretar en algo mas concreto. El ejemplo mas claro es de las estructuras de datos tradicionales: Pilas, Listas, Colas, etc.. Esas estructuras pueden contener distintos tipos de datos: enteros, strings, objetos,... Debemos reescribir la logica de cada estructura para cada tio de dato? NO! Podemos definir una clase plantilla para la Lista, la cola, la pila etc, y luego simplemente invocarlas especificando el tipo de dato. Asi de facil.
Figura: un caballero de la orden de los Templates
Veamos este horrible ejemplo de lista (atencion a la complicadilla sintaxis)
/**
* Lista.hpp
* Clase que define una estructura de datos lista Generica
*
* Pello Xabier Altadill Izura
*/
using namespace std;
#include <iostream>
// Asi es como declaramos una clase plantilla
// template <class nombre_generico> class NombreClase
template <class GENERICO> class Lista {
public:
// Constructor
Lista();
// Constructor
Lista(GENERICO elemento);
// Constructor copia
Lista(Lista const &);
// Destructor
~Lista();
// agregar elemento
void agregar(Lista *nodo);
// se mueve hasta el siguiente dato
Lista* siguiente();
// comprueba si existe un elemento
bool existe(GENERICO dato);
// comprueba si existe un elemento
GENERICO getDato() { return this->dato;}
private:
// un elemento que apunta a otra lista, asi sucesivamente
Lista *ladealao;
// el dato es del tipo GENERICO
GENERICO dato;
}; |
/**
* Lista.cpp
* Programa que implementa la clase de Lista generica
*
* Pello Xabier Altadill Izura
* Compilacion: g++ -c Lista.cpp
*
*/
#include "Lista.hpp"
// En la implementacion debemos detallar el tipo de dato,
// especificando todo el tema de plantilla, o sea que en lugar
// de poner Lista:: delante de cada funcion debemos poner TODO
// el churro siguiente
// template <class GENERICO> Lista<GENERICO>::nombreFuncion
// Constructor
template <class GENERICO> Lista<GENERICO>::Lista() {
ladealao = 0;
//dato = 0;
cout << "Nueva lista creada." << endl;
}
// Constructor
template <class GENERICO>
Lista<GENERICO>::Lista(GENERICO elemento) {
ladealao = 0;
dato = elemento;
cout << "Nueva lista creada. Dato inicial: " << dato << endl;
}
// Constructor copia
template <class GENERICO> Lista<GENERICO>::Lista(Lista
const & original) {
ladealao = new Lista;
ladealao = original.ladealao;
dato = original.dato;
}
// Destructor
template <class GENERICO> Lista<GENERICO>::~Lista() {
}
// agregar elemento: AL LORO con donde se pone el retonno
template <class GENERICO> void
Lista<GENERICO>::agregar(Lista *nodo) {
nodo->ladealao = this;
ladealao = 0;
}
// se mueve hasta el siguiente dato
template <class GENERICO> Lista<GENERICO>*
Lista<GENERICO>::siguiente() {
return ladealao;
}
//Lista template <class GENERICO> Lista<GENERICO>::siguiente();
// comprueba si existe un elemento
template <class GENERICO> bool
Lista<GENERICO>::existe(GENERICO dato) {
return false;
} |
/**
* Nombres.hpp
* Clase que define los nombres. No es mas que una
cobaya para probar el template
*
* Pello Xabier Altadill Izura
*/
// Esta clase la usaremos en el template, no hay que definir nada en especial
class Nombre {
public:
// Constructor
Nombre():nombre("Jezabel") {}
// Constructor
Nombre(char *nombre) {
this->nombre = nombre;
}
// Constructor copia
Nombre(Nombre const &);
// Destructor
~Nombre(){}
// agregar elemento
char* getNombre() const { return this->nombre;}
private:
// el dato
char *nombre;
}; |
/**
* Nombres.cpp
* Programa que implementa la clase nombres y utilza los templates
* para crear una lista de nombres.
*
* Pello Xabier Altadill Izura
* Compilando: g++ -o Nombre Lista.o Nombre.cpp
*/
#include "Nombre.hpp"
#include "Lista.hpp"
// Constructor copia
Nombre::Nombre(Nombre const & original) {
nombre = new char;
nombre = original.getNombre();
}
// Funcion principal para las pruebas
int main () {
// Asi es como se implementan objetos con clases plantilla
Lista<Nombre> listanombres;
Lista<Nombre> *tmp, *final;
Nombre test = Nombre("Prince");
// podemos definir Listas de cualquier tipo basico
Lista<int> listaenteros;
// guardamos la posicion inicial; final es un puntero, le pasamos la direccion
final = &listanombres;
// vamos a crear unos cuantos NODOS y los añadimos
tmp = new Lista<Nombre>;
tmp->agregar(final);
final = tmp;
// otra mas...
tmp = new Lista<Nombre>;
tmp->agregar(final);
final = tmp;
// otra mas...
tmp = new Lista<Nombre>;
tmp->agregar(final);
final = tmp;
// y ahora recorremos la lista:
tmp = &listanombres;
while (tmp) {
cout << tmp->getDato().getNombre() << endl;
tmp = tmp->siguiente();
}
return 0;
} |