Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Como declarar un tipo

Estas en el tema de Como declarar un tipo en el foro de C/C++ en Foros del Web. Buenas....voy a ver si en estos próximos 10-15 días soy capaz de terminar y darle un empujón a un proyecto que empecé hace más de ...
  #1 (permalink)  
Antiguo 28/06/2016, 04:57
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Como declarar un tipo

Buenas....voy a ver si en estos próximos 10-15 días soy capaz de terminar y darle un empujón a un proyecto que empecé hace más de 2 años y que lleva parado desde el verano pasado.

Es un programa que usa un grafo para hallar valores y datos. En su momento estuve preguntando sobre ello aquí.

Bueno, al grano. Una de las cosas que quiero hacer es que la clase Grafo funcione con plantilla para aceptar cualquier clase de datos en el nodo y en la arista. Eso está hecho desde el principio.

Pero luego, tengo unos functores que uso para tareas como recorrer el grafo. Estos functores no están parametrizados (Están ligados a los tipos de datos del programa que hace uso de él), así que quería solucionar esto antes de seguir, ya que por culpa de esto, no sólo los functores sino el propio grafo está ligado al tipo de datos concreto, y ya puesto me gustaría que fuera más flexible.

En fin, después de tanta historia, mi problema es que los functores no reconocen el tipo definido en Grafo, y no sé cómo arreglar esto.

Pongo para no cargar mucho la parte del Grafo que interesa:
Código C++:
Ver original
  1. //esto son functores
  2. class TratarArista;
  3. class TratarNodo;
  4. class TratarAristaConNiveles;
  5. class ImprimirArbol;

El nodo (con declaración previa de la arista)
Código C++:
Ver original
  1. template <typename DATOA, typename DATON>
  2. struct arista;//declaración previa
  3.  
  4. template <typename DATON, typename DATOA>
  5. struct nodo
  6. {
  7. ....................
La arista
Código C++:
Ver original
  1. template <typename DATOA, typename DATON>
  2. struct arista
  3. {
  4. ...................

Y el grafo
Código C++:
Ver original
  1. template <typename DATON, typename DATOA>
  2. class Grafo
  3. {
  4. public:
  5.  
  6.     typedef DATON datonodo_t;
  7.     typedef DATOA datoarista_t;
  8.     typedef nodo<datonodo_t,datoarista_t>* pNodo;
  9.     typedef arista<datoarista_t,datonodo_t>* pArista;
  10.     typedef nodo<datonodo_t,datoarista_t> t_nodo;
  11.     typedef arista<datoarista_t,datonodo_t> t_arista;
  12.     //constructor
  13. ................
__________________
Mi calculadora en Qt
  #2 (permalink)  
Antiguo 28/06/2016, 05:07
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Aprovechando que me he equivocado con la Vista Previa y le he dado a Enviar sigo en otro mensaje y así se verá menos denso el primero.

El caso es que con lo puesto arriba, puedo manejar mi grafo así:

Código C++:
Ver original
  1. #include <iostream>
  2. #include "Grafo.h"
  3. using namespace std;
  4.  
  5. typedef char datonodo_t;
  6. typedef int datoarista_t;
  7.  
  8. typedef nodo<datonodo_t,datoarista_t>* pNodo;
  9. typedef arista<datoarista_t,datonodo_t>* pArista;
  10. typedef nodo<datonodo_t,datoarista_t> t_nodo;
  11. typedef arista<datoarista_t,datonodo_t> t_arista;
  12.  
  13. int main()
  14. {
  15.     Grafo<datonodo_t,datoarista_t>g;
  16.     pNodo A = new t_nodo('A');
  17.     pNodo B = new t_nodo('B');
  18.     pNodo C = new t_nodo('C');
  19.  
  20.     pArista A_A=0;
  21.     pArista A_B = new t_arista(10);
  22.     pArista A_C = new t_arista(5);
  23.  
  24.     g.InsertarHijo(A,A,A_A,A_A);
  25.     g.InsertarHijo(A,B,A_A,A_B);
  26.     g.InsertarHijo(A,C,A_A,A_C);
  27.  
  28.     return 0;
  29. }

Por ahora vamos bien...sólo he tenido que volver a redefinir los tipos (supongo que eso se puede y se debe hacer para que no hay que andar redefiniendo tipos en cada clase o ficheros....

Pero ahora quiero recorrer el grafo, para ello tengo esta función en la clase Grafo:
Código C++:
Ver original
  1. void recorrerGrafo(pNodo& inicio, TratarArista& tratamiento);//TratarArista es el objeto functor

Entonces (por fin mi duda!!!) estoy reordenando el código de los functores, y lo primero que hago es volver a definir tipos:
Código C++:
Ver original
  1. #ifndef FUNCTORES_H
  2. #define FUNCTORES_H
  3.  
  4. #include "Grafo.h"
  5.  
  6.  //redefinicion de tipos
  7. typedef char datonodo_t;
  8. typedef int datoarista_t;
  9.  
  10. typedef nodo<datonodo_t,datoarista_t>* pNodo;
  11. typedef arista<datoarista_t,datonodo_t>* pArista;
  12. typedef nodo<datonodo_t,datoarista_t> t_nodo;
  13. typedef arista<datoarista_t,datonodo_t> t_arista;
  14.  
  15. struct TratarArista
  16. {    //miembros:
  17. ....................

Y aquí es cuando me tira el error, ya que me dice que ni nodo ni arista son tipos

Y las preguntas:

1.- Cómo hago para que me reconozca los tipos. En el main.cpp hago lo mismo y no me da problema
2.- Cómo hago para que esta definición de tipos no tenga que declararla en cada clase o en cada fichero?
__________________
Mi calculadora en Qt
  #3 (permalink)  
Antiguo 28/06/2016, 06:28
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Como declarar un tipo

Tu pregunta tiene formato bikini (enseña mucho pero oculta lo verdaderamente importante).

Entre otras cosas es imposible probar esos fragmentos de código para jugar con los errores de cara a ofrecer respuestas consistentes... y a estas alturas de la vida sabrás que los templates no son sencillos de manejar.

Creo que deberías aportar más información o, al menos, un ejemplo compilable mínimo que permita reproducir el problema.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #4 (permalink)  
Antiguo 28/06/2016, 09:09
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Pues la verdad es que si. Lo que pasa es que el código es algo extenso por eso no lo mostré entero.

Como estaba intentando depurar la clase Grafo, la he cogido y la estaba trasteando por fuera del programa.

Por otro lado estoy pensando que los functores no tienen que estar tan aislados del programa que los maneja. De hecho esa es precisamente su misión, aislar el grafo y crear funciones "ad hoc" adaptadas al programa que va a hacer uso del grafo. Espero estar no muy equivocado en esto....esto es la consecuencia de coger el programa un año después y volver a reconsiderar cosas que en su día ya las tenía más que claras.

Por cierto, que estoy intentando pegar el código pero es largo y no me deja
__________________
Mi calculadora en Qt
  #5 (permalink)  
Antiguo 28/06/2016, 09:31
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Como declarar un tipo

Puedes usar un servicio online para publicar el código, dividirlo en varios mensajes o intentar simplificarlo para que quepa en una única respuesta
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #6 (permalink)  
Antiguo 28/06/2016, 12:27
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Bueno, estaba pensando en subir el código a github, pero precisamente quería asearlo y depurarlo un poco (o mucho) antes de hacerlo.

Voy a tratar de ponerlo partido.
Grafo.h:
Código C++:
Ver original
  1. #ifndef GRAFO_H
  2. #define GRAFO_H
  3.  
  4. #include <stack>
  5. #include <list>
  6. #include <utility>
  7. #include "Functores.h"
  8.  
  9. class TratarArista;
  10. class TratarNodo;
  11. class TratarAristaConNiveles;
  12. class ImprimirArbol;
  13.  
  14. template <typename DATOA, typename DATON>
  15. struct arista;//declaración previa
  16.  
  17. template <typename DATON, typename DATOA>
  18. struct nodo
  19. {
  20.     DATON datonodo;
  21.     unsigned short int nPadres;
  22.     nodo<DATON,DATOA>* siguiente;
  23.     arista<DATOA,DATON>* adyacente;
  24.     //constructor
  25.     nodo (DATON N=0, unsigned short int numPadres=0, nodo<DATON,DATOA>* s=0, arista<DATOA, DATON>* a=0):datonodo(N),nPadres(numPadres),siguiente(s),adyacente(a) {}
  26.     //constructor copia
  27.     nodo (const nodo<DATON,DATOA>& n)
  28.     {
  29.         //std::cout<<"nodo Constructor copia"<<std::endl;
  30.         datonodo=n.datonodo;
  31.         nPadres=n.nPadres;
  32.         siguiente=0;
  33.         adyacente=0;
  34.     }
  35.     //destructor
  36.     ~nodo()
  37.     {
  38.         siguiente=0;
  39.         adyacente=0;
  40.         //borrar pila?
  41.         //borrar datonodo?
  42.         std::cout<<"Destructor nodo"<<std::endl;
  43.     }
  44.     //operador de asignacion
  45.     nodo& operator = (const nodo<DATON, DATOA>& n)
  46.     {
  47.         if (this!=&n)
  48.             {
  49.                 datonodo=n.datonodo;
  50.                 nPadres=n.nPadres;
  51.                 siguiente=0;
  52.                 adyacente=0;
  53.             }
  54.         return *this;
  55.     }
  56. };
  57.  
  58. template <typename DATOA, typename DATON>
  59. struct arista
  60. {
  61.     DATOA datoarista;
  62.     nodo<DATON,DATOA>* destino;
  63.     arista<DATOA,DATON>* siguiente;
  64.     arista<DATOA,DATON>* anterior;
  65.     //constructores
  66.     arista(DATOA A=0, nodo<DATON,DATOA>* d=0, arista<DATOA,DATON>* s=0, arista<DATOA,DATON>* an=0):datoarista(A),destino(d),siguiente(s), anterior(an) {}
  67.     arista (const arista<DATOA,DATON>& a)
  68.     {
  69.         datoarista=a.datoarista;
  70.         destino=0;
  71.         siguiente=0;
  72.         anterior=0;
  73.     }
  74.     //operador de asignacion
  75.     arista& operator = (const arista<DATOA, DATON>& a)
  76.     {
  77.         if (this!=&a)
  78.             {
  79.                 datoarista=a.datoarista;
  80.                 destino=0;
  81.                 siguiente=0;
  82.                 anterior=0;
  83.             }
  84.         return *this;
  85.     }
  86. };
  87.  
  88. template <typename DATON, typename DATOA>
  89. class Grafo
  90. {
  91. public:
  92.  
  93.     typedef DATON datonodo_t;
  94.     typedef DATOA datoarista_t;
  95.     typedef nodo<datonodo_t,datoarista_t>* pNodo;
  96.     typedef arista<datoarista_t,datonodo_t>* pArista;
  97.     typedef nodo<datonodo_t,datoarista_t> t_nodo;
  98.     typedef arista<datoarista_t,datonodo_t> t_arista;
  99.     //constructor
  100.     Grafo():Raiz(0),nNodos(0) {std::cout<<"Constructor grafo"<<std::endl;}
  101.     //constructor copia
  102.     Grafo (const Grafo& G);
  103.     //sobrecarga del operador =
  104.     Grafo& operator=(const Grafo& G);
  105.  
  106.     //funciones
  107.     /************auxiliares de nodos y aristas***************/
  108.     void anadirNodo (pNodo& n);
  109.     void eliminarNodo(pNodo& n);
  110.     void anadirArista (pNodo& NodoOrigen, pNodo& NodoDestino, pArista& precedente, pArista& NuevaArista);
  111.     void eliminarArista (pArista& A);
  112.     /*********insertar,eliminar,copiar elementos del grafo*******************/
  113.     void InsertarHijo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista);
  114.     void borrarNodos(pArista& A);
  115.     void CopiarNodo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista);
  116.     /******funciones para recorrer el grafo*************************/
  117.     void recorrerHijos(const pNodo& padre, TratarArista& tratamiento);
  118.     void recorrerGrafo(pNodo& inicio, TratarArista& tratamiento);
  119.     void recorrerGrafoConNiveles(pNodo& inicio, TratarAristaConNiveles& tratamiento, int n=0);
  120.     void recorrerAncestros(pNodo& n,TratarNodo& tratamiento);
  121.     void recorrerNodos(TratarNodo& tratamiento);
  122.     /**********comprobaciones necesarias****************/
  123.     bool esReferenciaCircular(pNodo& padre, pNodo& hijo);
  124.     bool existeHermano (pNodo& padre, pNodo& hijo);
  125.     bool existeNodo (const pNodo& n);
  126.     /***********otras*******************************/
  127.     void guardaAristas (pNodo& n);
  128.     void guardaAristasNivel (pNodo& n, int nivel);
  129.     pNodo posicionarseEnNodo(datonodo_t dato);
  130.     /***********consultoras*************************/
  131.     int LeeNumNodos()const {return nNodos;}
  132.     int NivelNodoPadre(pNodo& padre) const;
  133.     /****************funciones para la lista de hojas********************/
  134.     //poner aqui
  135.  
  136.  
  137.     //Destructor
  138.     ~Grafo();
  139.  
  140.     //private:
  141.     pNodo Raiz;
  142.     int nNodos;
  143.     std::stack<pArista> pila;
  144.     std::stack<std::pair<pArista,int> >pilaniveles;
  145.     std::list<pNodo>listaHojas;
  146. };
__________________
Mi calculadora en Qt
  #7 (permalink)  
Antiguo 28/06/2016, 12:31
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Grafo.h (continuación):
Código C++:
Ver original
  1. //********************//
  2. //destructor del grafo//
  3. //********************//
  4. template <typename datonodo_t, typename datoarista_t>
  5. Grafo<datonodo_t,datoarista_t>::~Grafo()
  6. {
  7.     std::cout<<"Iniciamos el destructor"<<std::endl;
  8.     pArista A;
  9.     //meto todas las arista del nodo Raiz en la pila
  10.     guardaAristas(Raiz);
  11.  
  12.     //empiezo a borrar todas las ramas que hay en la pila
  13.     while (!pila.empty())
  14.         {
  15.             A=pila.top();
  16.             pila.pop();
  17.             borrarNodos(A);
  18.         }
  19.     delete Raiz;
  20.     //~listaHojas();
  21.     std::cout<<"Borrada la raiz"<<std::endl;
  22. }
  23.  
  24. //*****************//
  25. //constructor copia//
  26. //*****************//
  27. template <typename datonodo_t, typename datoarista_t>
  28. Grafo<datonodo_t, datoarista_t>::Grafo (const Grafo<datonodo_t, datoarista_t>& G)
  29. {
  30.     std::cout<<"CONSTRUCTOR COPIA"<<std::endl;
  31.     //Raiz
  32.     pNodo indice1=G.Raiz;
  33.     Raiz=new t_nodo (*indice1);
  34.     pNodo indice=Raiz;
  35.     pArista indiceA=indice1->adyacente;
  36.     int i=0;
  37.     while (indice1->siguiente)
  38.         {
  39.             indiceA=indice1->adyacente;
  40.             //std::cout<<"Hasta aqui "<<i+1<<std::endl;
  41.  
  42.             while (indiceA)
  43.                 {
  44.                     pNodo hijo=posicionarseEnNodo(indiceA->destino->datonodo);//creo un nodo con el contenido del nodo origen hijo
  45.                     if (hijo==0)
  46.                         {
  47.                             hijo=new t_nodo(*indiceA->destino);
  48.                         }
  49.                     pArista A= new t_arista(*indiceA);
  50.                     InsertarHijo(indice,hijo,A->anterior,A);
  51.                     indiceA=indiceA->siguiente;
  52.                 }
  53.  
  54.             indice1=indice1->siguiente;
  55.             indice=indice->siguiente;
  56.             i++;
  57.         }
  58.     listaHojas(G.listaHojas);//así o listaHojas=G.listaHojas?
  59.     std::cout<<"Copia terminada"<<std::endl;
  60. }
  61.  
  62. //*************************//
  63. //sobrecarga del operador =//
  64. //*************************//
  65.  
  66. template <typename datonodo_t, typename datoarista_t>
  67. Grafo<datonodo_t, datoarista_t>& Grafo<datonodo_t, datoarista_t>::operator=(const Grafo<datonodo_t, datoarista_t>& G)
  68. {
  69.     if (this!=&G)
  70.         {
  71.             delete Raiz;
  72.             //vacio la pila
  73.             while (!pila.empty())
  74.                 {
  75.                     pila.pop();
  76.                 }
  77.             pNodo indice1=G.Raiz;
  78.             Raiz=new t_nodo (*indice1);
  79.             pNodo indice=Raiz;
  80.             pArista indiceA=indice1->adyacente;
  81.             while (indice1->siguiente)
  82.                 {
  83.                     indiceA=indice1->adyacente;
  84.  
  85.                     while (indiceA)
  86.                         {
  87.                             pNodo hijo=posicionarseEnNodo(indiceA->destino->datonodo);//creo un nodo con el contenido del nodo origen hijo
  88.                             if (hijo==0)
  89.                                 {
  90.                                     hijo=new t_nodo(*indiceA->destino);
  91.                                 }
  92.                             pArista A= new t_arista(*indiceA);
  93.                             InsertarHijo(indice,hijo,A->anterior,A);
  94.                             indiceA=indiceA->siguiente;
  95.                         }
  96.  
  97.                     indice1=indice1->siguiente;
  98.                     indice=indice->siguiente;
  99.                 }
  100.             listaHojas=G.listaHojas;
  101.         }
  102.     return *this;
  103. }
  104.  
  105. //**************//
  106. //añadir un nodo//
  107. //**************//
  108.  
  109. template <typename datonodo_t, typename datoarista_t>
  110. void Grafo<datonodo_t,datoarista_t>::anadirNodo(pNodo& n)
  111. {
  112.     pNodo indice=Raiz;
  113.     //me posiciono al final de la lista
  114.     while (indice && indice->siguiente!=0)
  115.         {
  116.             indice=indice->siguiente;
  117.         }
  118.     indice->siguiente=n;
  119.     nNodos++;
  120. }
  121.  
  122. //****************//
  123. //eliminar un nodo//
  124. //****************//
  125.  
  126. template <typename datonodo_t, typename datoarista_t>
  127. void Grafo<datonodo_t,datoarista_t>::eliminarNodo(pNodo& n)
  128. {
  129.     pNodo anterior=Raiz;
  130.     //avanzo anterior hasta el nodo anterior al que quiero borrar
  131.     while (anterior->siguiente!=n)
  132.         {
  133.             anterior=anterior->siguiente;
  134.         }
  135.     if (anterior==Raiz)//primer elemento
  136.         {
  137.             Raiz->siguiente=n->siguiente;
  138.         }
  139.     else
  140.         {
  141.             anterior->siguiente=n->siguiente;
  142.         }
  143.     delete n;
  144.     nNodos--;
  145. }
  146.  
  147. //*****************//
  148. //añadir una arista//
  149. //*****************//
  150.  
  151. template <typename datonodo_t, typename datoarista_t>
  152. void Grafo<datonodo_t,datoarista_t>::anadirArista (pNodo& NodoOrigen, pNodo& NodoDestino, pArista& precedente, pArista& NuevaArista)
  153. {
  154.     if (!NodoOrigen->adyacente)//primera arista
  155.         {
  156.             NodoOrigen->adyacente=NuevaArista;
  157.             NuevaArista->destino=NodoDestino;
  158.             //std::cout<<"Primera arista"<<std::endl;
  159.         }
  160.     else
  161.         {
  162.             pArista Aux=NodoOrigen->adyacente;
  163.             while (Aux!=precedente && Aux->siguiente)
  164.                 {
  165.                     Aux=Aux->siguiente;
  166.                 }
  167.             NuevaArista->siguiente=Aux->siguiente;
  168.             Aux->siguiente=NuevaArista;
  169.             NuevaArista->destino=NodoDestino;
  170.             NuevaArista->anterior=Aux;
  171.         }
  172. }
  173.  
  174. //*******************//
  175. //eliminar una arista//
  176. //*******************//
  177.  
  178. template <typename datonodo_t, typename datoarista_t>
  179. void Grafo<datonodo_t,datoarista_t>::eliminarArista(pArista& A)
  180. {
  181.     pNodo indice=Raiz;
  182.     //veo si la arista a borrar es la adyacente de algún nodo (primera arista)
  183.     while (indice && indice->adyacente!=A)
  184.         {
  185.             indice=indice->siguiente;
  186.         }
  187.     if (indice)//si finalmente la arista a borrar es adyacente de indice
  188.         {
  189.             //si es arista única
  190.             if (!A->anterior && !A->siguiente)
  191.                 {
  192.                     indice->adyacente=0;
  193.                     listaHojas.remove(indice);
  194.                 }
  195.             else
  196.                 {
  197.                     indice->adyacente=A->siguiente;
  198.                 }
  199.         }
  200.  
  201.     //inicio el borrado propiamente dicho
  202.     if (A->anterior)
  203.         {
  204.             A->anterior->siguiente=A->siguiente;
  205.         }
  206.     if (A->siguiente)
  207.         {
  208.             A->siguiente->anterior=A->anterior;
  209.         }
  210.     delete A;
  211. }
  212.  
  213. //***********************************************//
  214. //borrar todos los nodos que penden de una arista//
  215. //***********************************************//
  216.  
  217. template <typename datonodo_t, typename datoarista_t>
  218. void Grafo<datonodo_t,datoarista_t>::borrarNodos(pArista& A)
  219. {
  220.     pNodo hijo=A->destino;
  221.     //quitar un padre al nodo hijo
  222.     if (hijo->nPadres>0) hijo->nPadres--;
  223.     //si todavía es hijo de algún padre....
  224.     if (hijo->nPadres)
  225.         {
  226.             //...me limito a borrar la arista que une al padre con el hijo
  227.             eliminarArista(A);
  228.         }
  229.     else //si se queda huerfanito
  230.         {
  231.             //si el hijo es hoja no tiene aristas que salgan de él, luego adyacente apunta a 0
  232.             if (!hijo->adyacente)
  233.                 {
  234.                     //me posiciono en la arista a borrar
  235.                     eliminarArista(A);
  236.                     listaHojas.remove(hijo);
  237.                     eliminarNodo(hijo);//lo saco de la lista general de nodos
  238.                 }
  239.             else
  240.                 {
  241.                     guardaAristas(hijo);
  242.                     eliminarArista(A);
  243.                     eliminarNodo(hijo);
  244.                     while (!pila.empty())
  245.                         {
  246.                             A=pila.top();
  247.                             pila.pop();
  248.                             borrarNodos(A);
  249.                         }
  250.                 }
  251.         }
  252. }
  253. //**************************//
  254. //insertar un hijo a un nodo//
  255. //**************************//
  256.  
  257. template <typename datonodo_t, typename datoarista_t>
  258. void Grafo<datonodo_t,datoarista_t>::InsertarHijo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista)
  259. {
  260.     //primer elemento
  261.     if (Raiz==0)
  262.         {
  263.             Raiz=hijo;
  264.             listaHojas.push_back(Raiz);
  265.             nNodos++;
  266.         }
  267.     else
  268.         {
  269.             if (!existeHermano(padre,hijo))
  270.                 {
  271.                     listaHojas.remove(padre);//el padre deja de ser hijo...para convertirse en padre :-)
  272.                     hijo->nPadres++;//añado un padre
  273.                     //solo añado el nodo si es nuevo
  274.                     if (!existeNodo(hijo))
  275.                         {
  276.                             anadirNodo(hijo);
  277.                             listaHojas.push_back(hijo);
  278.                         }
  279.                     anadirArista(padre, hijo, precedente, NuevaArista);
  280.                 }
  281.             else std::cout<<"2 nodos iguales no pueden tener el mismo padre"<<std::endl;
  282.         }
  283.     /*std::cout<<"Lista de hojas: "<<std::endl;
  284.     for (auto it=listaHojas.begin();it!=listaHojas.end();it++)
  285.     {
  286.         std::cout<<((*it)->datonodo.LeeCodigo())<<" - ";
  287.     }
  288.     std::cout<<std::endl;*/
  289. }
__________________
Mi calculadora en Qt
  #8 (permalink)  
Antiguo 28/06/2016, 12:33
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Grafo.h (continuación):
Código C++:
Ver original
  1. //************************************//
  2. //copiar un nodo existente a otro nodo//
  3. //************************************//
  4.  
  5. template <typename datonodo_t, typename datoarista_t>
  6. void Grafo<datonodo_t,datoarista_t>::CopiarNodo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista)
  7. {
  8.     if (padre)
  9.         {
  10.             //eliminamos la posibilidad de tener dos nodos iguales bajo el mismo padre
  11.             if (esReferenciaCircular(padre,hijo))
  12.                 {
  13.                     std::cout<<"Referencia circular"<<std::endl;
  14.                 }
  15.             else
  16.                 {
  17.                     InsertarHijo(padre,hijo, precedente, NuevaArista);
  18.                 }
  19.         }
  20.     else std::cout<<"No hay padre al que copiar!!!"<<std::endl;
  21. }
  22.  
  23. //**********************************************************************//
  24. //recorre sólamente los nodos hijos directos que penden de un nodo padre//
  25. //**********************************************************************//
  26.  
  27. template <typename datonodo_t, typename datoarista_t>
  28. void Grafo<datonodo_t,datoarista_t>::recorrerHijos(const pNodo& padre, TratarArista& tratamiento)
  29. {
  30.     if (padre->adyacente!=0)
  31.         {
  32.             pArista A=padre->adyacente;
  33.             while (A->siguiente!=0)
  34.                 {
  35.                     tratamiento(A);
  36.                     A=A->siguiente;
  37.                 }
  38.             tratamiento(A);
  39.         }
  40. }
  41.  
  42. //*************************************//
  43. //recorrer el arbol a partir de un nodo//
  44. //*************************************//
  45.  
  46. template <typename datonodo_t, typename datoarista_t>
  47. void Grafo<datonodo_t,datoarista_t>::recorrerGrafo(pNodo& inicio, TratarArista& tratamiento)
  48. {
  49.     pArista A;
  50.     if (inicio)
  51.         {
  52.             guardaAristas (inicio);//meto las aristas en la pila
  53.             while (!pila.empty())
  54.                 {
  55.                     A=pila.top();
  56.                     pila.pop();
  57.                     pila.pop();
  58.                     tratamiento(A);
  59.                     recorrerGrafo(A->destino,tratamiento);
  60.                 }
  61.         }
  62. }
  63.  
  64.  
  65. //****************************************************************************//
  66. //recorrer el arbol a partir de un nodo con informacion del nivel de cada nodo//
  67. //****************************************************************************//
  68.  
  69. template <typename datonodo_t, typename datoarista_t>
  70. void Grafo<datonodo_t,datoarista_t>::recorrerGrafoConNiveles(pNodo& inicio, TratarAristaConNiveles& tratamiento, int n)
  71. {
  72.     pArista A;
  73.     if (inicio)
  74.         {
  75.             guardaAristasNivel(inicio,n);
  76.             while (!pilaniveles.empty())
  77.                 {
  78.                     A=pilaniveles.top().first;
  79.                     n=pilaniveles.top().second+1;
  80.                     pilaniveles.pop();
  81.                     std::pair<pArista,int>prov;
  82.                     prov.first=A;
  83.                     prov.second=n;
  84.                     tratamiento(prov);
  85.                     recorrerGrafoConNiveles(A->destino,tratamiento,n);
  86.                 }
  87.         }
  88. }
  89.  
  90. //***************************************************//
  91. //busca todos los ancestros de un nodo dado          //
  92. //***************************************************//
  93.  
  94. template <typename datonodo_t, typename datoarista_t>
  95. void Grafo<datonodo_t,datoarista_t>::recorrerAncestros(pNodo& n,TratarNodo& tratamiento)
  96. {
  97.     std::list<pNodo>listanodos;
  98.     typename std::list<pNodo>::iterator it;
  99.     pNodo indice=Raiz;
  100.  
  101.     while (indice)
  102.         {
  103.             if (indice->adyacente)
  104.                 {
  105.                     pArista A=indice->adyacente;
  106.                     while (A)
  107.                         {
  108.                             if (A->destino==n)
  109.                                 {
  110.                                     listanodos.push_back(indice);
  111.                                     tratamiento(indice);
  112.                                     //std::cout<<"El nodo "<<indice->datonodo.LeeCodigo()<<" es padre de "<<A->destino->datonodo.LeeCodigo()<<std::endl;
  113.                                     break;
  114.                                 }
  115.                             else
  116.                                 {
  117.                                     A=A->siguiente;
  118.                                 }
  119.                         }
  120.                 }
  121.             indice=indice->siguiente;
  122.         }
  123.  
  124.     for (it=listanodos.begin(); it!=listanodos.end(); ++it)
  125.         {
  126.             if (*it!=Raiz)
  127.                 {
  128.                     recorrerAncestros(*it, tratamiento);
  129.                 }
  130.         }
  131. }
  132.  
  133. //*********************************//
  134. //muestra todos los nodos del grafo//
  135. //*********************************//
  136.  
  137. template <typename datonodo_t, typename datoarista_t>
  138. void Grafo<datonodo_t,datoarista_t>::recorrerNodos(TratarNodo& tratamiento)
  139. {
  140.     pNodo indice=Raiz;
  141.     while (indice!=0)
  142.         {
  143.             tratamiento(indice);
  144.             indice=indice->siguiente;
  145.         }
  146. }
  147.  
  148. //*********************************************************************//
  149. //busca si un nodo que quiero copiar como hijo de otro es padre de éste//
  150. //necesario para evitar referencias circulares                         //
  151. //*********************************************************************//
  152.  
  153. template <typename datonodo_t, typename datoarista_t>
  154. bool Grafo<datonodo_t,datoarista_t>::esReferenciaCircular(pNodo& padre, pNodo& hijo)
  155. {
  156.     if (padre==hijo)
  157.         {
  158.             std::cout<<"Referencia $$ circular"<<std::endl;
  159.             return true;
  160.         }
  161.     else
  162.         {
  163.             pArista A;
  164.             bool encontrado=false;
  165.             guardaAristas(hijo);
  166.             while (!pila.empty())
  167.                 {
  168.                     A=pila.top();
  169.                     pila.pop();
  170.                     if (A->destino==padre)
  171.                         {
  172.                             //vacio la pila
  173.                             while (!pila.empty())
  174.                                 pila.pop();
  175.                             std::cout<<"Referencia circular"<<std::endl;
  176.                             return true;
  177.                         }
  178.                     return encontrado || esReferenciaCircular(padre,A->destino);
  179.                 }
  180.         }
  181.     return false;
  182. }
__________________
Mi calculadora en Qt
  #9 (permalink)  
Antiguo 28/06/2016, 12:35
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Grafo.h (final):
Código C++:
Ver original
  1. //*************************************************************//
  2. //comprueba la existencia de un nodo igual al que quiero copiar//
  3. //necesario para evitar tener dos nodos iguales colgando del   //
  4. //mismo padre                                                  //
  5. //*************************************************************//
  6.  
  7. template <typename datonodo_t, typename datoarista_t>
  8. bool Grafo<datonodo_t,datoarista_t>::existeHermano (pNodo& padre, pNodo& hijo)
  9. {
  10.     pArista A=padre->adyacente;
  11.     while (A!=0)
  12.         {
  13.             //std::cout<<"posicionada la arista"<<A<<std::endl;
  14.             if (A->destino==hijo)
  15.                 {
  16.                     return true;
  17.                 }
  18.             A=A->siguiente;
  19.         }
  20.  
  21.     //std::cout<<"No hay gemelos"<<std::endl;
  22.     return false;
  23. }
  24.  
  25. //*********************************************//
  26. //comprueba la presencia de un nodo en la lista//
  27. //para evitar su inclusión por duplicado       //
  28. //*********************************************//
  29.  
  30. template <typename datonodo_t, typename datoarista_t>
  31. bool Grafo<datonodo_t,datoarista_t>::existeNodo (const pNodo& n)
  32. {
  33.     pNodo indice=Raiz;
  34.     if (n==indice)
  35.         return true;
  36.     else
  37.         {
  38.             while (indice->siguiente)
  39.                 {
  40.                     indice=indice->siguiente;
  41.                     if (n==indice)
  42.                         {
  43.                             return true;
  44.                         }
  45.                 }
  46.         }
  47.     return false;
  48. }
  49.  
  50. //***************************************************//
  51. //guarda las aristas que penden de un nodo en la pila//
  52. //***************************************************//
  53.  
  54. template <typename datonodo_t, typename datoarista_t>
  55. void Grafo<datonodo_t,datoarista_t>::guardaAristas (pNodo& n)
  56. {
  57.     pArista A;
  58.  
  59.     if (n && n->adyacente) //si hay aristas
  60.         {
  61.             A=n->adyacente;
  62.             //me posiciono en la última arista
  63.             while (A->siguiente!=0)
  64.                 {
  65.                     A=A->siguiente;
  66.                 }
  67.             //empiezo el recorrido hacia atrás
  68.             while (A->anterior!=0)
  69.                 {
  70.                     pila.push (A); //meto la arista en la pila
  71.                     A=A->anterior;
  72.                 }
  73.             pila.push (A); //meto la primera arista en la pila*/
  74.         }
  75. }
  76.  
  77. //**************************************************************//
  78. //guarda las aristas y el nivel que penden de un nodo en la pila//
  79. //**************************************************************//
  80.  
  81. template <typename datonodo_t, typename datoarista_t>
  82. void Grafo<datonodo_t,datoarista_t>::guardaAristasNivel (pNodo& n, int nivel)
  83. {
  84.     pArista A;
  85.     std::pair<pArista,int> pareja;
  86.     pareja.second=nivel;
  87.  
  88.     if (n && n->adyacente) //si hay aristas
  89.         {
  90.             A=n->adyacente;
  91.             //me posiciono en la última arista
  92.             while (A->siguiente!=0)
  93.                 {
  94.                     A=A->siguiente;
  95.                 }
  96.             //empiezo el recorrido hacia atrás
  97.             while (A->anterior!=0)
  98.                 {
  99.                     pareja.first=A;
  100.                     pilaniveles.push (pareja); //meto la arista en la pila
  101.                     A=A->anterior;
  102.                 }
  103.             pareja.first=A;
  104.             pilaniveles.push (pareja); //meto la arista en la pila
  105.         }
  106. }
  107.  
  108.  
  109. template <typename DATON, typename DATOA>
  110. nodo<DATON,DATOA>* Grafo<DATON,DATOA>::posicionarseEnNodo(datonodo_t dato)
  111. {
  112.     pNodo indice=Raiz;
  113.  
  114.     while (indice->siguiente!=0 && indice->datonodo!=dato)
  115.         {
  116.             indice=indice->siguiente;
  117.         }
  118.     if (indice->datonodo!=dato)
  119.         {
  120.             //std::cout<<"Nodo inválido"<<std::endl;
  121.             return 0;
  122.         }
  123.     else return indice;
  124. }
  125.  
  126. //*******************************//
  127. //obtiene el nivel del nodo padre//
  128. //** ****************************//
  129.  
  130. template <typename DATON, typename DATOA>
  131. int Grafo<DATON,DATOA>::NivelNodoPadre(pNodo& padre) const
  132. {
  133.     pNodo indice=Raiz;
  134.     pArista A;
  135.     while (indice)
  136.     {
  137.         if (indice->adyacente)
  138.         {
  139.             A=indice->adyacente;
  140.             while (A)
  141.             {
  142.                 if (A->destino==padre)
  143.                 {
  144.                     return A->nivel;
  145.                 }
  146.                 A=A->siguiente;
  147.             }
  148.         }
  149.         indice=indice->siguiente;
  150.     }
  151.     return -1; //en caso de error o de que no haya encotnrado el nodo padre.....
  152. }
  153.  
  154. #endif // GRAFO_H
__________________
Mi calculadora en Qt
  #10 (permalink)  
Antiguo 28/06/2016, 12:44
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Bueno, a todo esto, el tema inicial lo he corregido haciendo una declaración previa de "nodo" y "arista". Lo intenté antes pero olvidaba que al ser plantillas había de definri su correspondiente template

El programa main.cpp podría ser el que sale en el post 2

Y ahora los functores. Estos son los que quiero redefinir.

Aquí poco puedo enseñar, porque he modificado bastantes cosas (que como siempre no guardo). Son funciones que hacen algo cuando, por ejemplo, recorro todos los nodos del grafo (mostrar el contenido del nodo, sumarlos, etc)

Edito:
He modificado un poco el código de esta clase, ya que una vez solucionado el problema de que no me reconocía los tipos nodo y arista, ahora el problema lo tengo a la hora de imprimir, puesto que no me reconoce destino que es del tipo struct arista<int, char>* (pArista)
|77|error: invalid use of incomplete type ‘struct arista<int, char>’|

Functores.h:
Código C++:
Ver original
  1. #ifndef FUNCTORES_H
  2. #define FUNCTORES_H
  3.  
  4. #include <iomanip>
  5.  
  6. #include "Grafo.h"
  7.  
  8. //definicion de tipos
  9. typedef char datonodo_t;
  10. typedef int datoarista_t;
  11.  
  12. template <typename DATOA, typename DATON>
  13. struct nodo;
  14.  
  15. template <typename DATOA, typename DATON>
  16. struct arista;
  17.  
  18. typedef nodo<datonodo_t,datoarista_t>* pNodo;
  19. typedef arista<datoarista_t,datonodo_t>* pArista;
  20. typedef nodo<datonodo_t,datoarista_t> t_nodo;
  21. typedef arista<datoarista_t,datonodo_t> t_arista
  22. struct TratarAristaConNiveles
  23. {
  24.     //typedef arista<MedCert,Concepto>* pArista;
  25.     std::pair<pArista,int>pareja;
  26.     std::list<pArista> &listaAristasConMediciones;
  27.     TratarAristaConNiveles(std::pair<pArista,int>par, std::list<pArista>&l):pareja(par),listaAristasConMediciones(l){}
  28.  
  29.     virtual void operator()(std::pair<pArista,int>P)=0;
  30. };
  31.  
  32. struct ImprimirArbol:public TratarAristaConNiveles
  33. {
  34.     ImprimirArbol(std::pair<pArista,int>par, std::list<pArista>&l):TratarAristaConNiveles(par,l){}
  35.     void operator()(std::pair<pArista,int>P)
  36.     {
  37.         std::cout<<P.second<<"-";
  38.         std::cout<<"|";
  39.         for (int i=0;i<P.second;i++)
  40.         {
  41.             std::cout<<"----";
  42.         }
  43.         std::cout<<">";
  44.  std::cout<<
  45.                 std::setw(1)<<std::setfill(' ')<<P.first->destino->datonodo;
  46.                 std::cout<<std::setiosflags(std::ios::right)<<  std::endl;
  47.     }
  48. };
  49.  
  50. #endif // FUNCTORES_H

Muchas gracias, como siempre
__________________
Mi calculadora en Qt

Última edición por dehm; 29/06/2016 a las 00:35
  #11 (permalink)  
Antiguo 29/06/2016, 01:26
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Como declarar un tipo

Del código que has puesto yo veo los siguientes problemas:

Te falta un punto y coma después de t_arista:

Código C++:
Ver original
  1. typedef arista<datoarista_t,datonodo_t> t_arista
  2. struct TratarAristaConNiveles

Te falta cerrar una llave:

Código C++:
Ver original
  1. struct ImprimirArbol:public TratarAristaConNiveles
  2. {
  3.     ImprimirArbol(std::pair<pArista,int>par, std::list<pArista>&l):TratarAristaConNiveles(par,l){}
  4.     void operator()(std::pair<pArista,int>P)
  5.     {
  6.         std::cout<<P.second<<"-";
  7.         std::cout<<"|";
  8.         for (int i=0;i<P.second;i++)
  9.         {
  10.             std::cout<<"----";
  11.         }
  12.         std::cout<<">";
  13.     } // <<<---- ESTA!!!!
  14. ..................//aquí ya tengo otro tipo de error, pero no es el que me preocupa ahora
  15. };

Y con eso a mí ya me compila.

Ahora una pequeña labor de refactorización:

El código de functores.h no necesita conocer la clase grafo sino únicamente a arista y nodo. Parece lógico entonces mover estas dos clases a un fichero independiente para que functores.h no tenga que incluir grafo.h. También puedes eliminar las declaration forward de arista y nodo que tienes en functores.h.

arista.h
Código C++:
Ver original
  1. #ifndef ARISTA_H
  2. #define ARISTA_H
  3.  
  4. template <typename,typename>
  5. struct nodo;
  6.  
  7. template <typename DATOA, typename DATON>
  8. struct arista
  9. {
  10.   DATOA datoarista;
  11.   nodo<DATON,DATOA>* destino;
  12.   arista<DATOA,DATON>* siguiente;
  13.   arista<DATOA,DATON>* anterior;
  14.  
  15.   // ...
  16. };
  17.  
  18. #endif // ARISTA_H

nodo.h
Código C++:
Ver original
  1. #ifndef NODO_H
  2. #define NODO_H
  3.  
  4. template<typename, typename>
  5. struct arista;
  6.  
  7. template <typename DATON, typename DATOA>
  8. struct nodo
  9. {
  10.   DATON datonodo;
  11.   unsigned short int nPadres;
  12.   nodo<DATON,DATOA>* siguiente;
  13.   arista<DATOA,DATON>* adyacente;
  14.  
  15.   // ...
  16. };
  17.  
  18. #endif // NODO_H
Por otro lado no veo nada en functores.h que impida convertir las clases en templates para no tener que crear especializaciones en ese punto:

Código C++:
Ver original
  1. #ifndef FUNCTORES_H
  2. #define FUNCTORES_H
  3.  
  4. #include <iomanip>
  5.  
  6. #include "arista.h"
  7. #include "nodo.h"
  8.  
  9. template<class DATOA, class DATON>
  10. struct TratarAristaConNiveles
  11. {
  12.     typedef nodo<DATON,DATOA>* pNodo;
  13.     typedef arista<DATOA,DATON>* pArista;
  14.    
  15.     //typedef arista<MedCert,Concepto>* pArista;
  16.     std::pair<pArista,int>pareja;
  17.     std::list<pArista> &listaAristasConMediciones;
  18.     TratarAristaConNiveles(std::pair<pArista,int>par, std::list<pArista>&l):pareja(par),listaAristasConMediciones(l){}
  19.  
  20.     virtual void operator()(std::pair<pArista,int>P)=0;
  21. };
  22.  
  23. template<class DATOA, class DATON>
  24. struct ImprimirArbol
  25.   : public TratarAristaConNiveles<DATOA,DATON>
  26. {
  27.   // ...
  28. };

El código anterior no compilará porque un template no puede definir una función virtual pura. Hay dos posibles formas de solucionarlo: más herencia o darle una implementación básica a dicha función. Yo personalmente prefiero la primera, pero no es implementable porque la firma del operador función es dependiente de los tipos del template así que solo nos queda la segunda opción:

Código C++:
Ver original
  1. template<class DATOA, class DATON>
  2. struct TratarAristaConNiveles
  3. {
  4.     typedef nodo<DATON,DATOA>* pNodo;
  5.     typedef arista<DATOA,DATON>* pArista;
  6.    
  7.     //typedef arista<MedCert,Concepto>* pArista;
  8.     std::pair<pArista,int>pareja;
  9.     std::list<pArista> &listaAristasConMediciones;
  10.     TratarAristaConNiveles(std::pair<pArista,int>par, std::list<pArista>&l):pareja(par),listaAristasConMediciones(l){}
  11.  
  12.     virtual void operator()(std::pair<pArista,int>P)
  13.     {}
  14. };

Ahora el problema que tenemos es que la clase hija no va a reconocer las declaraciones de pNodo y pArista declaradas en TratarAristaConNiveles. Este error tiene que ver con la forma en la que se tratan los templates en C++.

La forma más sencilla de lidiar con este problema, desde mi punto de vista, pasa por declarar una función traits que declare por sí misma los tipos pArista y pNodo para no tener que redeclararlos cada dos por tres:

Código C++:
Ver original
  1. template<class,class>
  2. struct arista;
  3.  
  4. template<class,class>
  5. struct nodo;
  6.  
  7. template<class DATOA, class DATON>
  8. struct traits
  9. {
  10.   typedef arista<DATOA,DATON>* pArista;
  11.   typedef nodo<DATON,DATOA>* pNodo;
  12. };

Y se usa así:

Código C++:
Ver original
  1. template<class DATOA, class DATON>
  2. struct TratarAristaConNiveles
  3. {
  4.   typedef traits<DATOA,DATON> myTraits;
  5.   typedef typename myTraits::pNodo pNodo;
  6.   typedef typename myTraits::pArista pArista;
  7.  
  8.   //typedef arista<MedCert,Concepto>* pArista;
  9.   std::pair<pArista,int>pareja;
  10.   std::list<pArista> &listaAristasConMediciones;
  11.   TratarAristaConNiveles(std::pair<pArista,int>par,
  12.                          std::list<pArista>&l)
  13.     : pareja(par),
  14.       listaAristasConMediciones(l)
  15.   { }
  16.  
  17.   virtual void operator()(std::pair<pArista,int>P)=0;
  18. };
  19.  
  20. template<class DATOA, class DATON>
  21. struct ImprimirArbol
  22.   : TratarAristaConNiveles<DATOA,DATON>
  23. {
  24.   typedef typename TratarAristaConNiveles<DATOA,DATON>::myTraits myTraits;
  25.   typedef typename myTraits::pNodo pNodo;
  26.   typedef typename myTraits::pArista pArista;
  27.  
  28.   ImprimirArbol(std::pair<pArista,int>par,
  29.                 std::list<pArista>&l)
  30.     : TratarAristaConNiveles<DATOA,DATON>(par,l)
  31.   { }
  32. };

o así (si te quieres ahorrar un alias):

Código C++:
Ver original
  1. template <typename DATOA, typename DATON>
  2. struct arista
  3. {
  4.     typedef typename traits<DATOA,DATON>::pArista pArista;
  5.     typedef typename traits<DATOA,DATON>::pNodo pNodo;
  6.  
  7.     DATOA datoarista;
  8.     pNodo destino;
  9.     pArista siguiente;
  10.     pArista anterior;
  11. };

typename hay que ponerlo porque el tipo del que intentamos crear el alias es dependiente de un template... cosas del lenguaje.

Con C++11 quedaría algo más elegante, desde mi punto de vista:

Código C++:
Ver original
  1. struct TratarAristaConNiveles
  2. {
  3.   using myTraits = traits<DATOA,DATON>;
  4.   using pNodo    = typename myTraits::pNodo;
  5.   using pArista  = typename myTraits::pArista;
  6. };
  7.  
  8. template<class DATOA, class DATON>
  9. struct ImprimirArbol
  10.   : TratarAristaConNiveles<DATOA,DATON>
  11. {
  12.   using myTraits = typename TratarAristaConNiveles<DATOA,DATON>::myTraits;
  13.   using pNodo    = typename myTraits::pNodo;
  14.   using pArista  = typename myTraits::pArista;
  15. };

La ventaja de usar la clase traits es que podemos arrastrar esas definiciones a donde nos plazca de forma algo más sencilla que hacerlo a mano, donde tienes que recordar el orden de DATOA y DATON en cada declaración de nodo y arista.

Para rematar, dado que ahora tenemos templates nuevos, hay que actualizar el archivo grafo.h. Ahí podemos eliminar las declaration forward de TratarAristaConNiveles e ImprimirArbol, además de actualizar la firma de algunas funciones:

Código C++:
Ver original
  1. void recorrerGrafoConNiveles(pNodo& inicio,
  2.                              TratarAristaConNiveles<DATOA,DATON>& tratamiento,
  3.                              int n=0);

Y creo que como primer paso es suficiente. Seguir refactorizando ese código lleva su tiempo sobretodo para comprenderlo (paso imprescindible para que el nuevo código funcione correctamente jejeje), pero con estos cambios al menos es compilable.

Yo empezaría por meter la clase traits en grafo para tener una declaración unificada de los tipos pArista y pNodo.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Última edición por eferion; 29/06/2016 a las 02:12
  #12 (permalink)  
Antiguo 29/06/2016, 15:38
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Bueno eferion:

Como otra veces, no me has dado una respuesta sino una clase magistral

Ahora toca enterarse de todo, que hay muchos matices en ese código que me has puesto.
Por lo pronto, he hecho la plantilla de los functores pero sin traits, y ya me funciona.
Antes de enterarme de lo de traits, voy a entender lo que tengo, sobre todo lo que se refiere a herencia de clases con plantillas...hasta me he puesto a leer y resulta que typename y class no son exactamente lo mismo.

La parte mala es que las dos semanas que quería dedicarle a terminar mi programa casi que lo voy a usar para afianzar estos conocimientos, que o no tenía o los tengo de forma muy elemental.

Saludos y gracias de nuevo....seguro que sigo dando la brasa con esto
__________________
Mi calculadora en Qt
  #13 (permalink)  
Antiguo 30/06/2016, 16:31
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Para entender todo lo que me has puesto y ver más en profundidad el tema de plantillas y herencias, he estado un rato leyendo este artículo que para mi está siendo bastante asequible:
http://www.codeproject.com/Articles/...mplates-Part-1

http://www.codeproject.com/Articles/...Templates-Part

(Voy por la parte 1)
Entonces habla de como implementar el constructor copia en una clase con plantilals, con este ejemplo:

Código C++:
Ver original
  1. Pair(const Pair<Type1, Type2>& OtherPair) :
  2.   first(OtherPair.first),
  3.   second(OtherPair.second)
  4.  {}

Además advierte expresamente que no poner los tipos dará un error:

Please note that it is very much required to specify template type arguments of Pair<>, for the argument of this copy-constructor. The following specification wouldn't make sense, since Pair is not a non-template type:

Código C++:
Ver original
  1. Pair(const Pair& OtherPair) // ERROR: Pair requires template-types

Pero yo acabo de hacerlo "mal" a ver qué pasa y me funciona:
Código C++:
Ver original
  1. template<class T1, class T2>
  2. struct pareja
  3. {
  4.     T1 first;
  5.     T2 second;
  6.  
  7.     //constructor
  8.     pareja():first(T1()),second(T2()) {}
  9.     pareja(const T1&t1,const T2&t2):first(t1),second(t2) {}
  10.     pareja(const pareja& p) //<----aqui lo estoy haciendo mal pareja(const pareja<T1,T2>& p)
  11.     {
  12.         first=p.first;
  13.         second=p.second;
  14.     }
  15.     bool operator == (const pareja<T1,T2>& Other) const
  16.     {
  17.         return first == Other.first &&
  18.                second == Other.second;
  19.     }
  20. };

¿Sabéis por qué es así?
Gracias como siempre!
__________________
Mi calculadora en Qt
  #14 (permalink)  
Antiguo 30/06/2016, 17:42
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 9 meses
Puntos: 27
Respuesta: Como declarar un tipo

No está mal hecho, ambas opciones son válidas y tienen la misma semántica de copia
  #15 (permalink)  
Antiguo 01/07/2016, 05:03
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Como declarar un tipo

Ah, pues gracias por la aclaración. Eso me dice que no debo de tomar el artículo tan en serio
__________________
Mi calculadora en Qt

Etiquetas: declarar, int, programa, tipo
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:23.