Este artículo es una continuación de Programación Genérica.
Siguiendo con la introducción que hizo Eduardo y con ayuda de unos amigos, voy a explicar que son y para que se usan los templates, uno de los recursos mas poderosos de C++.
Según la wikipedia:
Las plantillas son el mecanismo de C++ para implantar el paradigma de la programación genérica. Permiten que una clase o función trabaje con tipos de datos abstractos, especificándose más adelante cuales son los que se quieren usar.
Las templates nos permiten crear estructuras de datos que no dependen de si vamos a ingresarles un entero, una letra, o cualquier otro tipo de dato que se nos ocurra. ¿como es esto? Se nos permite, mediante simples modificaciones, adaptar nuestras estructuras.
Yo usaré una clase con un array (vector) que iré modificando para que reciba enteros, luego char y por ultimo float(reales). Esta es una de las mejores maneras de reutilizar código!
A la antigua, esto requería que se hiciera 3 clases diferentes con 3 arrays diferentes… pero usando templates lo haré en una sola.
El siguiente es el código:
/*********ARCHIVO PRUEBA.H ***********/
#ifndef PRUEBA_H_
#define PRUEBA_H_
#include <iostream>
/**
* Aqui empiezan las diferencias a una declaración ordinaria.
* La linea siguiente define que cada vez que aparezca "t"
* se modificará el dato por otro que mas adelante definiremos.
*/
template <class t>
class prueba
{
private:
/** como vemos, el array no es ni de enteros **/
t array[5]; /** ni de char ni de otros datos sino que es
/** de datos tipo "t"
/**/
int poscicion;
public:
prueba(){}
virtual ~prueba(){}
bool ingresar_datos(t & datos)
{
if (poscicion<5)
{
array[poscicion]=datos;
poscicion ++;
return true;
}
else
{
return false;
}
}
/**
* nuevamente vemos que esta funcion nos devuelve un dato de tipo "t"
*/
t mostrar_datos(int & pos)
{
if (pos<=4 && pos>=0)
return array[pos];
else
return array[1];
}
};
#endif /*PRUEBA_H_*/
Bueno, hasta aquí vimos que donde supuestamente debía aparecer un tipo de dato aparecía una “t”, esto le indicará al compilador que se debe tomar a “t” como el tipo de variable que a continuacion definiremos en el main de abajo.
A continuación, dejo una posible implementación en un archivo main.cpp:
#include "prueba.h"
#include <iostream>
using namespace std;
int main (){
int dato1 = 1;
char dato2 = 'a';
float dato3 = 3.14;
int pos = 0;
prueba<float>prueba3;
prueba<char>prueba2;
prueba<int>prueba1;
prueba1.ingresar_datos(dato1);
cout << prueba1.mostrar_datos(pos) << endl;
prueba2.ingresar_datos(dato2);
cout << prueba2.mostrar_datos(pos) << endl;
prueba3.ingresar_datos(dato3);
cout << prueba3.mostrar_datos(pos) << endl;
return 0;
}
Como vemos, con esta simple declaración cambiamos de una clase común, a una clase que puede admitir tanto enteros como punteros como cualquier otro dato que se nos ocurra; hicimos una infinidad de pasos en pocas líneas ya que con modificar <float> por <char> o por <int> cambiamos nuestra clase para que admita un dato diferente.
Ahora, quizás esta forma de definir nuestras clases y crear objetos se vea un poco complicada, pero yo recomiendo que se familiaricen bien con los templates porque en mas de una ocasión nos ahorrarán muchas pero muchas líneas de código.
Mas adelante explicaré como crear una lista enlazada con templates… y ahí veremos la gran utilidad de los templates.
¿Y tu, utilizas esta potente herramienta?
Hola Gustavo:
Leia el articulo, para ver el grado de profundidad sobre el tema de templates que hay aqui, pues me parece que esta muy bien para que la gente que desconoce el uso de templates en c++ puedan hacer sus primeras funciones, aunque creo que es importante dar una introduccion sobre clases y sobre constructores/destructores y eso…bueno eso desde mi punto de vista, ya que si vienen usuarios con el conocimiento ya de clases pues no tendrian ningun problema al comenzar esto (lo hablo por experiencia), otro punto es un error de tecleo en la sentencia if, te voy a pegar el codigo y lo comentare si sabras donde lo debes corregir
bool ingresar_datos(t & datos)
{
if (poscicion>=4) //debe ser <=4 || <5
{ …etc…
Por lo demas pues esta muy bien hecho
Si hay alguna forma de ayudar algun momento haganmelo saber
Saludos.
Bueno gracias por la correccion aunque en mi compilador me funciona a la perfeccion es todo una cuestion de que IDE utilices. En cuanto a lo de que habria que hacer una introduccion al tema clases tienes toda la razon y muy pronto voy a andar con eso pero quize subir esto ya que anteriormente habia una introduccion a lo que es la programacion generica, pero sí, quien no sepa clases no va a entender nada XD, bueno por lo menos por ahora. Espero que sigas visitando el blog y si quieres ponte en contacto con Eduardo ya que todo aquel que este dispuesto a ayudar bienvenido sea.
Pues bien, te cuento algo que pasaba conmigo, cuando usaba Dev-c++ y hacia algo asi (usando punteros):
char *tmp = new char;
cin >> tmp;
y si en la ejecucion del programa escribias por ejemplo esto:
“Temporal”
Pues si haces un cout de *tmp pues aparecera la letra “T” todo en orden, pero cuando se hace algo asi:
cout << tmp;
Pues aparecera toda la palabra, asi que esto quiere decir que en nuestro char se ha almacenado toda una cadena y no da error, lo que sucede es que esta escribiendolo en una parte en memoria que el mismo Dev-c++ automaticamente reserva para ejecucion de aplicaciones, pero si el mismo codigo lo mandas a Visual C++ pues obtendras el error en tiempo de ejecucion, ya que no puede haber mas de un caracter reservado para un char
El codigo podria en tanto trabajar sin problemas, aunque desde ya posee errores…
Aunque viendo el codigo nuevamente el int poscicion de la clase nunca fue definido, eso deberia estar en el constructor…poner como valor inicial un 0
Saludos
PD: ya me puse en contacto con Eduardo
Ya fué correjido el artículo gracias E2A por avisar del error, un gusto tenerte como lector
Si ya me di cuenta de lo que hablabas, y es como vos decis. me quede pensando en otra cosa y por eso no lo modifique antes, y el int no hace falta inicializarlo ya que los compiladores modernos lo inicializa automaticamente guardando un cero como valor o por lo menos eso hace el eclipse (es lo malo de programar mucho tiempo con el mismo IDE jajaja) te olvidas de que quizas no corra en otro entorno, en cuanto a lo de los char lo q tendrias q haber hecho es poner
char* tmp =new char[8];
asi te asignabas 8 pociciones y luego con cargarle simplemente a tmp ya te lo guardaba todo y el error del q hablas que tira el dev creo que ya fue solucionado en las ultimas versiones no lo dejemos mal parado al dev q es software libre XD y otra vez gracias por tus comentarios.
Muy bien explicado el concepto de templates. Pero ahora necesito saber como usarlo con listas dinamicas, por favor. Algun tutorial bueno?
mmmm
pero el tema es sumamente interesante para redactar y hablar sobre él
.
Dani, no conosco ningún tutorial bueno para pasarte
Un saludo!
Y gracias por comentar y darnos la idea sobre que escribir en próximas entradas.
Amigo … revise esto de los templates, debo reconocer que muy bien explicado mis felicitaciones pero al momento de compilar el codigo que tu tienes, si lo obseravas bien la poscicion en ningun momento pasas un argumento por ende el programa produce un fallo de segmentacion…..la solucion es sencilla solo debes agregar algo al constructor…
prueba(){
poscicion = 0;
}
y con eso se soluciona :p
salu2!
uso los templates en diferentes proyectos y sus respectivas librerias.. las STL’s(standard template libraries) que seguramente estas últimas muchos han usado sin siquiera saberlo ya que estan en forma de los MAPS, VECTOR, etc etc.. los templates serían algo asi como lso generics de c#, y para serles sinceros no extraño mucho ese lenguaje.. jejeje.. excepto cuando se trata de manejar los mas fácilmente posible una cadena por ejemplo pero una vez adentrado en c++ y aprendiendo las herramientas correctas como los templates se daran cuenta de lo increiblemente poderoso que peude llegar a ser programar en c++…. felicidades por el artículo..