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; } |