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