Template es como generic de java. En resumen.
Pero voy a explayarme un poco más pero solo un poco con un ejemplo. Supongamos que tenemos que hacer una lista de enteros, lo hacemos y listo. Pero inmediatamente necesitamos una lista de string y lo hacemos. Pero inmediatamente necesitamos una lista de double y creo que se va entendiendo la idea.
En los lenguajes de tipado estáticos, tenemos ese problema, por cada tipo debemos hacer una estructura de ese tipo particular. Y de este problema nace un concepto que se lo llama programación genérica. Es decir, la programación genérica nos permite programar estructuras sin definir un tipo determinado y esto nos permite generalizar.
Esto ayuda muchísimo a la reutilización y en c++ tenemos una librería estandar que nos provee estructuras genéricas. Pilas, colas, mapas, etc.
Veamos un ejemplo de un árbol b :
arbol.h
#ifndef ARBOL_H
#define ARBOL_H
template <class T>
//con template digo que mi clase va a ser una plantilla
class Arbol
{
private:
Arbol<T> * izq = 0;
Arbol<T> * der = 0;
T dato;
public:
Arbol(T dato);
void agregar(T otroDato);
void listarEnOrden();
};
#endif // ARBOL_H
arbol.cpp
#include "arbol.h"
#include <iostream>
using namespace std;
template <class T>
Arbol<T>::Arbol(T dato)
{
this->dato = dato;
}
template <class T>
void Arbol<T>::agregar(T otroDato){
if (this->dato > otroDato) {
if (this->izq != 0) {
this->izq->agregar(otroDato);
} else {
this->izq = new Arbol(otroDato);
}
} else {
if (this->der != 0) {
this->der->agregar(otroDato);
} else {
this->der = new Arbol(otroDato);
}
}
}
template <class T>
void Arbol<T>::listarEnOrden() {
if (this->izq != 0) {
this->izq->listarEnOrden();
}
cout << this->dato << " ";
if (this->der != 0) {
this->der->listarEnOrden();
}
}
Veamos como usar este árbol:
#include <iostream>
#include "arbol.cpp"
using namespace std;
int main()
{
Arbol<int> arbolEntero(5); // Como vemos le tengo que indicar el tipo donde estaba T
arbolEntero.agregar(3);
arbolEntero.agregar(2);
arbolEntero.agregar(6);
arbolEntero.agregar(7);
arbolEntero.listarEnOrden();
return 0;
}
Otro ejemplo un map:
map.h
#ifndef MAP_H
#define MAP_H
template <class K, class V>
class Map
{
private:
int count = 0;
K * keys;
V * values;
public:
Map();
void put(K key, V value);
V get(K key);
};
#endif // MAP_H
map.cpp:
#include "map.h"
template <class K, class V>
Map<K,V>::Map()
{
this->count = 0;
}
template <class K, class V>
void Map<K,V>::put(K key, V value){
K * auxKey = new K (count + 1);
K * auxValue = new V (count + 1);
for(int i = 0; i < count; i++){
auxKey[i]= this->keys[i];
auxValue[i] = this->values[i];
}
auxKey[count] = key;
auxValue[count] = value;
if (this->count > 0) {
delete this->keys;
delete this->values;
}
count++;
this->keys = auxKey;
this->values = auxValue;
}
template <class K, class V>
V Map<K,V>::get(K key){
int index = 0;
for(int i = 0; i < count; i++){
if (key == this->keys[i]) {
index = i;
}
}
return this->values[index];
}
Veamos como usar el map:
#include <iostream>
#include "map.cpp"
using namespace std;
int main()
{
Map<int,int> myMap = Map<int,int>();
myMap.put(1,2);
myMap.put(2,3);
myMap.put(4,5);
cout<< myMap.get(1) << " "<<myMap.get(2) << " "<< myMap.get(4);
return 0;
}