comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Plantillas en C++

  • 0 Respuestas
  • 1866 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Dharok

  • *
  • Underc0der
  • Mensajes: 111
  • Actividad:
    0%
  • Reputación 0
  • Siempre atento! Aun vivo.
    • Ver Perfil
    • Email
« en: Abril 21, 2010, 04:45:13 pm »
Plantillas en C++

Las plantillas nos permiten especificar, con un solo segmento de código, un rango completo de funciones relacionadas (sobrecargadas), llamadas funciones de plantilla, o un rango completo de clases relacionadas, llamadas clases de plantilla.

Podríamos escribir una sola plantilla de función para una función de ordenamiento de arreglos y luego hacer que C++ generara automáticamente funciones de plantilla separadas que ordenaran un arreglo de int, un arreglo de float, un arreglo de string, etc.

Podríamos escribir una sola plantilla de clase de pila y luego hacer que C++ generara automáticamente clases de plantillas separadas, tales como una clase de pila de int, una clase de pila de float, una clase de pila de string, etc.

Hay que observar la diferencia entre las plantillas de función y las funciones de plantilla: las plantillas de función y las plantillas de clase son como plantillas con las cuales trazamos formas, y las funciones de plantilla y las clases de plantilla son como los trazos separados, que tienen la misma forma pero pueden trazarse en colores diferentes, por ejemplo.

Plantillas de función

Las funciones sobrecargadas se utilizan normalmente para realizar operaciones similares sobre diferentes tipos de datos. Si las operaciones son idénticas para cada tipo, esto puede realizarse en forma más compacta y conveniente mediante el uso de plantillas de función. Basándose en los tipos de argumento que se proporcionan en las llamadas a esa función, el compilador genera automáticamente funciones de código objeto separadas para manejar adecuadamente cada tipo de llamada. En C esta tarea se puede realizar mediante macros creadas con la directiva de preprocesador #define.

Sin embargo las macros presentan la posibilidad de serios efectos secundarios y no permiten que el compilador realice revisión de tipo. Las plantillas de función proporcionan una solución compacta similar a la de las macros, pero permiten una revisión de tipo completa. Todas las definiciones de plantillas de función comienzan con la palabra clave témplate, seguida de una lista de parámetros formales para dicha plantilla encerrados entre paréntesis angulares (< y >), cada parámetro formal que representa un tipo debe estar precedido por la palabra clave class, como en:
Código: You are not allowed to view links. Register or Login
template <class T>
template <class Element Type>
template <class BorderType, class FillType>
Los parámetros formales de una definición de plantilla se utilizan (como sucedería con los argumentos de tipos integrados o de tipos definidos por el usuario) para especificar los tipos de argumentos de la función, para especificar el tipo de devolución de la función y para declarar variables en el interior de la función.

Para definir una plantillas de clase, se puede usar el siguiente formato:
Código: You are not allowed to view links. Register or Login
template <class T>
class Nombre { . . .uso del parámetro T en funciones o datos miembro.. }

Primer programa


El siguiente programa hace uso de plantillas para determinar el mínimo y máximo valor de un arreglo de elementos dado.
La primera función recibe tiene como parámetros un puntero al tipo de elemento dado y el número de elementos y retorna el menor de los elementos que se encuentran en el arreglo.
La segunda función recibe los mismos parámetros y retorna el mayor de los elementos presentes en el arreglo.
Finalmente en la función main, se hace una prueba de estas funciones, con arreglos de enteros y flotantes.
Código: C++
  1. #include <iostream.h>
  2. #include <conio.h>
  3.  
  4. template <class T>
  5. T minimo (T * Array, int num_elemen)
  6. {
  7.    T min= Array [0] ;
  8.  
  9.    for (int i=1; i< num_elemen; i++)
  10.         if( Array[ i ] < min)
  11.             min = Array [ i ];
  12.  
  13.    return min;
  14. } ;
  15.  
  16. template <class T>
  17. T maximo (T * Array, int num_elemen)
  18. {
  19.    T max= Array [0];
  20.  
  21.    for (int i=1; i< num_elemen; i++)
  22.         if( Array[ i ] > max)
  23.             max = Array [ i ];
  24.  
  25.    return max;
  26. };
  27.  
  28. void main(void)
  29. {
  30.    int ArrayInt [3] = { 2, 8, 6};
  31.    float ArrayFloat [3] = { 12.1, 8.7, 5.6 };
  32.    int i;
  33.    
  34.    cout<<"Arreglo de enteros: ";
  35.    for (i=0; i<3; i++)
  36.          cout << ArrayInt[ i ] << " ";
  37.  
  38.    cout << endl << "Numero minimo: " << minimo (ArrayInt, 3) << endl
  39.          <<"Numero maximo: " << maximo (ArrayInt, 3) << endl << endl;
  40.  
  41.    cout << "Arreglo de flotantes: ";
  42.    for (i=0; i<3; i++)
  43.         cout << ArrayFloat[ i ] << " ";
  44.         cout << endl <<"Numero minimo: " << minimo (ArrayFloat, 3) << endl
  45.                <<"Numero maximo: " << maximo (ArrayFloat, 3);
  46.  
  47.    getch();
  48. }
Segundo programa

En este programa se hace uso de plantillas, para elaborar una función que permita ordenar los elementos de un arreglo.
Esta función recibe tiene como parámetros, un puntero al tipo de elemento dado, y dos enteros que indican los índices del primero y último elemento.
Aquí se hace uso del algoritmo OrdenarShell para llevar a cabo la tarea. En la función principal se prueba esta plantilla con arreglos de enteros y flotantes.
Código: C++
  1. #include <iostream.h>
  2. #include <conio.h>
  3.  
  4. template <class T>
  5. void Ordenar ( T * a, int st, int fn)
  6. {
  7.    int i, j , k;
  8.    T item_a_ordenar;
  9.  
  10.    k = 1 ;
  11.  
  12.    do
  13.    {
  14.        k= 3 * k + 1;
  15.     } while (k < fn - st + 1) ;
  16.  
  17.    do
  18.    {
  19.        k /= 3 ;
  20.  
  21.        for (i= st+k; i<=fn; i++)
  22.        {
  23.              item_a_ordenar = a [ i ] ;
  24.              j = i ;
  25.  
  26.             while (item_a_ordenar < a [ j-k])
  27.             {
  28.                a [ j] =a [ j-k] ;
  29.                j -=k;
  30.  
  31.                if(j < st+k)
  32.                  break;
  33.             }
  34.  
  35.             a [j]=item_a_ordenar;
  36.         }
  37.    } while(k > 1);
  38. }
  39.  
  40. void main(void)
  41. {
  42.     int Arraylnt[3] = { 2, 3, 1 } ;
  43.     float ArrayFloat[3] = {25.0, 3.0, 45.2 } ;
  44.     int i ;
  45.  
  46.     cout << "Enteros: " << endl
  47.           << "Arreglo original: ";
  48.  
  49.     for (i=0; i<3; i++)
  50.           cout << Arraylnt[ i ] << " ";
  51.  
  52.     Ordenar(Arraylnt, 0, 2);
  53.     cout << endl << "Luego de ordenar: ";
  54.  
  55.     for (i=0; i<3; i++)
  56.           cout << Arraylnt[ i ] << " ";
  57.  
  58.  
  59.     cout << endl << endl
  60.           << "Flotantes: " << endl
  61.           << "Arreglo original: ";
  62.  
  63.     for (i=0; i<3; i++)
  64.           cout << ArrayFloat[ i ] << " ";
  65.  
  66.     Ordenar(ArrayFloat, 0, 2);
  67.     cout << endl << "Luego de ordenar: ";
  68.  
  69.     for (i=0; i<3; i++)
  70.           cout << ArrayFloat[ i ] << " ";
  71.  
  72.  
  73.     getch() ;
  74. }
Tercer programa

En este programa se implementa, mediante el uso de plantillas la clase NuevaPila, que consiste en una Pila, en la que se pueden llevar a cabo las operaciones como insertar y eliminar datos de la misma, mostrar en pantalla los datos de la pila.

Esta es una pila estática, con un número predefinido de 10 elementos.
En al función principal, se usa una pila de enteros, flotantes y
caracteres para poder llevar a cabo una prueba de la plantilla creada.
Código: C++
  1. #include <iostream.h>
  2. #include <conio.h>
  3.  
  4. enum estado_pila { OK, LLENA, VACIA };
  5.  
  6. template <class T>
  7. class NuevaPila
  8. {
  9.    int tamanyo;
  10.    T *tabla;
  11.    int cima;
  12.    estado_pila estado;
  13.  
  14.    public:
  15.              NuevaPila(int =10);
  16.              ~NuevaPila() { delete [] tabla; }
  17.              void meter (T);
  18.              T sacar ();
  19.              void visualizar ();
  20.              int num_elementos ();
  21.              int leer_tamanyo () { return tamanyo; }
  22. }
  23.  
  24. template <class T>
  25. NuevaPila <T> :: NuevaPila (int tam)
  26. {
  27.    tamanyo=tam;
  28.    tabla= new T [tamanyo] ;
  29.    cima=0;
  30.    estado=VACIA;
  31. }
  32.  
  33. template <class T>
  34. void NuevaPila <T> :: meter (T elemento)
  35. {
  36.    if( estado!=LLENA)
  37.        tabla [cima++]=elemento;
  38.     else cout << "*** Pila llena ***";
  39.  
  40.     if(cima>=tamanyo)
  41.        estado=LLENA;
  42.     else
  43.        estado=OK;
  44. }
  45.  
  46. template <class T>
  47. T NuevaPila <T> :: sacar ()
  48. {
  49.    T elemento=0;
  50.  
  51.    if(estado!=VACIA)
  52.       elemento=tabla[--cima];
  53.    else cout<<"*** Pila vac¡a ***";
  54.  
  55.    if(cima<=0)
  56.       estado=VACIA;
  57.    else
  58.       estado=OK;
  59.  
  60.    return elemento;
  61. }
  62.  
  63. template <class T>
  64. void NuevaPila <T> :: visualizar ()
  65. {
  66.    for (int i=cima-1; i >=0; i--)
  67.         cout << tabla[ i ] <<" ";
  68. }
  69.  
  70. template <class T>
  71. int NuevaPila <T> :: num_elementos ()
  72. {
  73.    return cima;
  74. }
  75.  
  76. void main()
  77. {
  78.    cout << "Probando pila de enteros";
  79.  
  80.    NuevaPila <int> s1 (5);
  81.    s1.meter(5);
  82.    s1.meter(10);
  83.    s1.meter(15);
  84.  
  85.    cout << endl << "Numero de elementos: " << s1.num_elementos() << endl <<"Pila: ";  
  86.    s1.visualizar();
  87.  
  88.    cout << endl << "Sacando elementos : "
  89.           << s1.sacar() <<" " << s1.sacar() << " " << s1.sacar() << endl;
  90.    s1.sacar();
  91.  
  92.    cout << endl << endl << "Probando pila de flotantes";
  93.    NuevaPila <float> s2 (5);
  94.    s2.meter(7.5);
  95.    s2.meter(10.2);
  96.    s2.meter(15.3);
  97.  
  98.    cout << endl << "Numero de elementos: " << s2.num_elementos() << endl
  99.          <<"Pila: ";
  100.    s2.visualizar();
  101.    cout << endl << "Sacando elementos : "
  102.            << s2.sacar() << " " << s2.sacar() << " " << s2.sacar() << endl;
  103.    s2.sacar ();
  104.  
  105.    cout << endl << endl << "Probando pila de caracteres";
  106.    NuevaPila <char> s3 (5);
  107.    s3.meter('m');
  108.    s3.meter('p');
  109.    s3.meter('s');
  110.  
  111.    cout << endl << "Numero de elementos: " << s3.num_elementos() << endl <<"Pila: ";
  112.     s3.visualizar();
  113.     cout << endl << "Sacando elementos : "
  114.           << s3.sacar () << " " << s3.sacar() << " " << s3.sacar() << endl;
  115.    s3.sacar();
  116.  
  117.  
  118.    getch();
  119. }
Cuarto ejemplo

Mediante el uso de plantillas cree una clase Cola, en la que se puedan llevar a cabo operaciones como: encolar, decolar e imprimir los datos miembro. Realice una función controladora para probar el uso de esta clase.
La clase NodoCola, tiene como amiga a la clase Cola.
Se presenta además una función para las opciones del usuario, y que se encarga de realizar las llamadas a las funciones de las clases. Esta
función es llamada desde main.
En la función main se ha usado como ejemplo una cola de enteros, aunque también se pudo haber usado otro tipo de datos como: char, double, y otros.
Código: C++
  1. #include <iostream.h>
  2. #include <conio.h>
  3. #include <assert.h>
  4.  
  5. template <class TIPONODO>
  6. class Cola;
  7.  
  8. ///////////////////////////////////
  9. // definicion clase NodoCola /////
  10. //////////////////////////////////
  11.  
  12. template <class TIPONODO>
  13. class NodoCola {
  14.       TIPONODO dato;                         // dato
  15.       NodoCola <TIPONODO> * sig;             // puntero siguiente nodo
  16.       public:
  17.          NodoCola (const TIPONODO &);    // constructor
  18.          TIPONODO getDato() const;       // devuelve dato del nodo
  19.  
  20.       friend class Cola <TIPONODO>;          // hace que Cola sea friend
  21. };
  22.  
  23. // constructor
  24. template <class TIPONODO>
  25. NodoCola <TIPONODO> :: NodoCola (const TIPONODO & info)
  26.      : dato(info), sig (0) { }
  27.  
  28. // devuelve una copia del dato que esta en el nodo
  29. template <class TIPONODO>
  30. TIPONODO NodoCola <TIPONODO> :: getDato() const {
  31.      return dato;
  32. }
  33.  
  34. // definicion enumeracion //
  35. enum bool { false, true };
  36.  
  37. //////////////////////////////////
  38. // definicion clase Cola /////////
  39. //////////////////////////////////
  40.  
  41. template <class TIPONODO>
  42. class Cola {
  43.       NodoCola <TIPONODO> * primero;          // puntero al primer nodo
  44.       NodoCola <TIPONODO> * ultimo;           // puntero al ultimo nodo
  45.       public:
  46.          Cola ();                         // constructor
  47.          ~Cola();                         // destructor
  48.          void encolar (const TIPONODO &); // permite insertar nodo
  49.          bool decolar (TIPONODO &);       // permite eliminar nodo
  50.          bool estaVacia() const;          // verifica si la cola esta vacia
  51.          void imprimir() const;              // imprime datos de la cola
  52.  
  53.       // funci¢n de utileria para asignar un nuevo nodo
  54.       NodoCola <TIPONODO> * getNuevoNodo (const TIPONODO &);
  55. };
  56.  
  57. // constructor predeterminado
  58. template <class TIPONODO>
  59. Cola <TIPONODO> :: Cola (): primero(0), ultimo(0) { }
  60.  
  61. // destructor
  62. template <class TIPONODO>
  63. Cola <TIPONODO> :: ~Cola () {
  64.      if( !estaVacia() ) {         // ingresa si la cola no esta vacia
  65.     cout<<"Eliminando nodos ..." << endl;
  66.  
  67.     NodoCola <TIPONODO> * actual = primero, *temporal;
  68.  
  69.     while (actual != 0) {     // borra los nodos restantes
  70.            temporal = actual;
  71.            cout<< temporal->dato << endl;
  72.            actual = actual->sig;
  73.            delete temporal;
  74.     }
  75.      }
  76.      cout << "Todos los nodos han sido eliminados" << endl << endl;
  77. }
  78.  
  79. // inserta un nodo
  80. template <class TIPONODO>
  81. void Cola <TIPONODO> :: encolar (const TIPONODO & valor) {
  82.      NodoCola <TIPONODO> * nuevo = getNuevoNodo (valor);
  83.  
  84.      if ( estaVacia() )                // si la cola esta vacia
  85.     primero=ultimo=nuevo;
  86.  
  87.      else {                           // si la cola no esta vacia
  88.        ultimo->sig=nuevo;
  89.        ultimo=nuevo;
  90.      }
  91. }
  92.  
  93. // elimina un nodo
  94. template <class TIPONODO>
  95. bool Cola <TIPONODO> :: decolar (TIPONODO & valor) {
  96.      if( estaVacia() )                // la cola esta vacia
  97.      return false;                // eliminacion no satisfactoria
  98.  
  99.      NodoCola <TIPONODO> *temporal = primero;
  100.  
  101.      if(primero==ultimo)
  102.     primero=ultimo=0;
  103.  
  104.      else
  105.       primero=temporal->sig;
  106.  
  107.      valor=temporal->dato;            // dato que se esta eliminando
  108.      delete temporal;
  109.      return true;                     // eliminacion satisfactoria
  110. }
  111.  
  112. // verifica si la cola esta vacia
  113. template <class TIPONODO>
  114. bool Cola <TIPONODO> :: estaVacia () const {
  115.      if (primero==0) return true;
  116.      return false;
  117. }
  118.  
  119. // imprime el contenido de la cola
  120. template <class TIPONODO>
  121. void Cola <TIPONODO> :: imprimir() const {
  122.      if ( estaVacia() ) {
  123.      cout<<"La lista esta vacia" << endl << endl;
  124.      return;
  125.      }
  126.  
  127.      NodoCola <TIPONODO> *actual = primero;
  128.  
  129.      cout<<"La cola es: ";
  130.  
  131.      while (actual!=0) {
  132.         cout<< actual->dato <<" ";
  133.         actual=actual->sig;
  134.      }
  135.  
  136.      cout << endl << endl;
  137. }
  138.  
  139. // funcion de utileria: devuelve un apuntador a un nodo recientemente asignado
  140. template <class TIPONODO>
  141. NodoCola <TIPONODO> * Cola <TIPONODO> :: getNuevoNodo (const TIPONODO & valor) {
  142.      NodoCola <TIPONODO> * nuevo = new NodoCola <TIPONODO> (valor);
  143.      assert(nuevo!=0);
  144.      return nuevo;
  145. }
  146.  
  147. /////////////////////////////////////////////////////////////////////////////
  148.  
  149. // funcion que prueba una cola
  150. template <class T>
  151. void probarCola ( Cola <T> & ObjetoCola) {
  152.  
  153.      T valor;
  154.      int opcion;
  155.  
  156.      for (;;){
  157.            cout<<endl<<"(1) Insertar, (2) Eliminar, (3) Imprimir, (4) Salir"<<endl;
  158.            cout<<"Seleccion: ";
  159.            cin>>opcion;
  160.  
  161.            switch( opcion ){
  162.               case 1:
  163.                  cout<<"Ingrese dato: ";
  164.                  cin>> valor;
  165.                  ObjetoCola.encolar(valor);
  166.                  break;
  167.  
  168.               case 2:
  169.                  if(ObjetoCola.decolar(valor))
  170.                 cout<<"Dato " << valor <<" eliminado" << endl << endl;
  171.  
  172.                  else cout<<"No puede eliminar : la cola esta vacia" << endl << endl;
  173.  
  174.                  break;
  175.  
  176.               case 3:
  177.                  ObjetoCola.imprimir();
  178.                  break;
  179.            }
  180.            if(opcion==4) break;
  181.      }
  182. }
  183.  
  184. // funcion principal
  185. void main(){
  186.      clrscr();
  187.      Cola <int> ColaEnteros;
  188.      probarCola (ColaEnteros);
  189.  
  190. }
« Última modificación: Febrero 08, 2014, 05:21:20 pm por Expermicid »
You are not allowed to view links. Register or Login

 

¿Te gustó el post? COMPARTILO!