Ver Mensaje Individual
  #11 (permalink)  
Antiguo 16/04/2015, 00:18
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Diferenciar entrada de datos por consola

Cita:
Iniciado por vangodp Ver Mensaje
Hombre... Para lo que sirve si lo sé
No pretendía enseñarte para qué sirven... solo mostrarte un par de trucos a usar con los templates ;)

Cita:
Iniciado por vangodp Ver Mensaje
pero lo que has puesto ahí de ejemplo me va tardar un año entenderlo jajajaj.
Ya será menos.

La jerarquía de los nodos se compone de dos clases: NodoBase y Nodo<T>

NodoBase obliga a que las especializaciones de Nodo<T> implementen una serie de funciones (en el caso del ejemplo, sólo una). Este diseño te permite usar polimorfismo y usar todos los Nodo<T> (Nodo<int>, Nodo<float>, Nodo<string>...) como si fuesen un mismo tipo de objeto.

La gracia de este diseño es que podría almacenar elementos más complejos sin demasiado esfuerzo. En el siguiente ejemplo añado una especialización del template que almacena una estructura en vez de un tipo nativo:

Código C++:
Ver original
  1. #include <iostream>
  2. #include <string>
  3.  
  4. class NodoBase
  5. {
  6.   public:
  7.  
  8.     NodoBase( )
  9.       : _siguiente( nullptr )
  10.     { }
  11.  
  12.     virtual ~NodoBase( )
  13.     { }
  14.  
  15.     void SetSiguiente( NodoBase* siguiente )
  16.     { _siguiente = siguiente; }
  17.  
  18.     NodoBase* Siguiente( ) const
  19.     { return _siguiente; }
  20.  
  21.     virtual void Pintar( std::ostream& out ) const = 0;
  22.  
  23.   private:
  24.  
  25.     NodoBase* _siguiente;
  26. };
  27.  
  28. template< typename _TYPE_ >
  29. class Nodo : public NodoBase
  30. {
  31.   public:
  32.     Nodo( _TYPE_ valor )
  33.       : _valor( valor )
  34.     { }
  35.  
  36.     ~Nodo( )
  37.     { }
  38.  
  39.     virtual void Pintar( std::ostream& out ) const
  40.     { out << _valor; }
  41.  
  42.   private:
  43.  
  44.     _TYPE_ _valor;
  45. };
  46.  
  47. struct ObjetoComplejo
  48. {
  49.   std::string nombre;
  50.   int edad;
  51. };
  52.  
  53. template< >
  54. class Nodo< ObjetoComplejo > : public NodoBase
  55. {
  56.   public:
  57.     Nodo( ObjetoComplejo valor )
  58.       : _valor( valor )
  59.     { }
  60.  
  61.     ~Nodo( )
  62.     { }
  63.  
  64.     virtual void Pintar( std::ostream& out ) const
  65.     { out << _valor.nombre << "(" << _valor.edad << ")"; }
  66.  
  67.   private:
  68.  
  69.     ObjetoComplejo _valor;
  70. };
  71.  
  72. class Lista
  73. {
  74.   public:
  75.  
  76.     Lista( )
  77.       : _primero( nullptr )
  78.     { }
  79.  
  80.     virtual ~Lista( )
  81.     {
  82.       while( _primero )
  83.       {
  84.         NodoBase* siguiente = _primero->Siguiente( );
  85.         delete _primero;
  86.         _primero = siguiente;
  87.       }
  88.     }
  89.  
  90.     template< class _TYPE_ >
  91.     void NuevoItem( _TYPE_ valor )
  92.     {
  93.       NodoBase* nuevoNodo = new Nodo< _TYPE_ >( valor );
  94.  
  95.       if ( !_primero )
  96.         _primero = nuevoNodo;
  97.       else
  98.       {
  99.         NodoBase* nodo = _primero;
  100.         while( nodo->Siguiente( ) )
  101.           nodo = nodo->Siguiente( );
  102.  
  103.         nodo->SetSiguiente( nuevoNodo );
  104.       }
  105.     }
  106.  
  107.     void Pintar( std::ostream& out )
  108.     {
  109.       if ( !_primero )
  110.       {
  111.         out << "Lista vacía" << std::endl;
  112.         return;
  113.       }
  114.  
  115.       _primero->Pintar( out );
  116.       NodoBase* nodo = _primero->Siguiente( );
  117.       while( nodo )
  118.       {
  119.         out << " -> ";
  120.         nodo->Pintar( out );
  121.         nodo = nodo->Siguiente( );
  122.       }
  123.  
  124.       out << std::endl;
  125.     }
  126.  
  127.   private:
  128.  
  129.     NodoBase* _primero;
  130. };
  131.  
  132. int main( )
  133. {
  134.   Lista lista;
  135.  
  136.   lista.NuevoItem( 1 );
  137.   lista.NuevoItem( 'c' );
  138.   lista.NuevoItem( "prueba" );
  139.   lista.NuevoItem( 4.56 );
  140.  
  141.   ObjetoComplejo complejo;
  142.   complejo.nombre = "pepe";
  143.   complejo.edad = 31;
  144.  
  145.   lista.NuevoItem( complejo );
  146.  
  147.   lista.Pintar( std::cout );
  148. }

Luego, lo que hace la clase "Lista" es almacenar una lista simple de elementos de tipo "NodoBase". La función que permite añadir nuevos elementos es un template, de tal forma que la especialización de la función es crear el nodo específico para el tipo T (por ejemplo, la especialización Pintar<int> es capaz de crear Nodo<int>). Esto quiere decir que, a la hora de la verdad, la función "Pintar" estará sobrecargada, existiendo una versión para cada tipo de nodo que deseemos añadir.

Una vez los nodos forman parte de la lista, el objeto "Lista" es capaz de interactuar con ellos haciendo uso de los métodos virtuales de "NodoBase". De esta forma puede, como he comentado antes, acceder a ciertas características de los nodos s