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

[SOLUCIONADO] Usar un método que tiene otro método como argumento

Estas en el tema de Usar un método que tiene otro método como argumento en el foro de C/C++ en Foros del Web. Hola de nuevo: Sigo con mi grafo y ahora me encuentro con otro problema. Tengo una clase Grafo. Esta clase tiene un método (en este ...
  #1 (permalink)  
Antiguo 03/02/2014, 05:10
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Usar un método que tiene otro método como argumento

Hola de nuevo:

Sigo con mi grafo y ahora me encuentro con otro problema.

Tengo una clase Grafo. Esta clase tiene un método (en este caso no es recursivo, pero igualmente me ha de tratar varios valores) así:
Código C++:
Ver original
  1. template <typename datonodo_t, typename datoarista_t>
  2. void Grafo<datonodo_t,datoarista_t>::recorrerHijos(pNodo& padre,void (*pfunc)(pArista& a))
  3. {
  4.     if (padre->adyacente!=0)
  5.         {
  6.             pArista A=padre->adyacente;
  7.              while (A->siguiente!=0)
  8.                 {
  9.                     pfunc();
  10.                     A=A->siguiente;
  11.                 }
  12.             pfunc();
  13.         }
  14. }

Siguiendo los consejos que me dió CalgaryCorpus en el anterior post relacionado, soy capaz de tratar las aristas que recorre el método...pero desde main.

Ahora tengo otra clase que contiene un Grafo, además de unos tipos abstractos en sus nodos/aristas.

Entonces ahora quiero hacer lo que hacía (por ejemplo imprimir) pero desde un método de la clase nueva.

Ahora tengo dos métodos:
Código C++:
Ver original
  1. void MostrarHijos()
  2. {
  3.     G.recorrerHijos(padre, imprimir);
  4. }

y

Código C++:
Ver original
  1. void imprimir(pArista a)
  2. {
  3.     cout<<a->destino->datonodo.LeeNombre()<<endl;
  4. }

Pues bien, me arroja un error:
Código:
<unresolved overloaded function type>)’
Buscando en Google me lleva a un error similar en StackOverflow, y parece que mi error se debe a que para invocar a la función imprimir() debo instanciar un objeto de la clase, y luego llamar al método de ese objeto.

Incluso aqui ponen un código de ejemplo....lo que pasa es que mis conocimientos no me dan para entender exactamente cómo resuelven el problema:
Código C++:
Ver original
  1. printf("%d\n", test([=](int v){return this->f2(v);}, 5));
The = there will capture this, which is what you need to call f2.

(esto que he pegado sólo tiene sentido leyendo el enlace a StackOverflow que he puesto.)

Bueno, pues en definitiva...¿como puedo hacer yo lo mismo?
O concretando...¿cómo uso una método de una clase que tiene otro método como argumento?

Gracias, como siempre!
  #2 (permalink)  
Antiguo 03/02/2014, 12:06
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: Usar un método que tiene otro método como argumento

¿Es imprimir() un metodo dentro de una clase?
Si es asi, no puede invocarse asi, o la firma del constructor de Grafo esta mal.

Hay una inconsistencia entre ambos.
Tal como está la firma y tal como esta definida imprimir, no tiene sentido que sea un metodo de la clase pues no usa nada de la clase, por lo que o bien la defines fuera de la clase, o la haces static

Código C++:
Ver original
  1. static void imprimir( ... )
  2. {
  3. }
para que la firma del constructor de Grafo calce.

Si requieres usar algo de la segunda clase, habrá que cambiar la firma del constructor de Grafo, pero hasta ahora esa no es tu necesidad.
__________________
Visita mi perfil en LinkedIn
  #3 (permalink)  
Antiguo 03/02/2014, 14:06
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: Usar un método que tiene otro método como argumento

Gracias por responder.

Efectivamente, de tantas vueltas que le he dado a la función, lo que he puesto no cuadraba:

Realmente es así:
Código C++:
Ver original
  1. template <typename datonodo_t, typename datoarista_t>
  2.     void Grafo<datonodo_t,datoarista_t>::recorrerHijos(pNodo& padre,void (*pfunc)(pArista& a))
  3.     {
  4.         if (padre->adyacente!=0)
  5.             {
  6.                 pArista A=padre->adyacente;
  7.                  while (A->siguiente!=0)
  8.                     {
  9.                         pfunc(A);
  10.                         A=A->siguiente;
  11.                     }
  12.                 pfunc(A);
  13.             }
  14.     }

También había probado a declarar la función fuera de la clase, pero si no maneja datos del grafo va bien, pero si los maneja no va.

Efectivamente, en principio la idea es que la clase que maneja al grafo y a los datos de los nodos y aristas, tenga el método imprimir.
Pero claro, entonces MostrarHijos() es un método de la clase que llama a otro método de la misma clase.
El cuerpo del método
Código C++:
Ver original
  1. void MostrarHijos()
  2.     {
  3.         G.recorrerHijos(padre, imprimir);
  4.     }

tiene un objeto G y un método recorrerHijos() de la clase Grafo, y un método -imprimir()-de la misma clase que la propia función que lo usa -MostrarHijos()-.

(Por cierto, que veo que tengo mal el título, puesto que el método "padre" no es que tenga a otro método de la misma clase como argumento, sino en el cuerpo del mismo)

Probaré lo de static...pero realmente me siento perdido, porque no sé cual es realmente el problema, o la lógica del problema.

Gracias!

(por cierto...como se edita el título del post?)

Última edición por dehm; 03/02/2014 a las 14:13
  #4 (permalink)  
Antiguo 03/02/2014, 14:21
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: Usar un método que tiene otro método como argumento

Una explicación mas extensa y árida.

En C es "fácil" manipular direcciones de memoria al interior de punteros.
Guardas las dirección de memoria, luego la usas, desreferenciando el puntero.

La definicion de las funciones queda en alguna dirección de memoria. Esta direccion es guardada en un puntero constante. Este puntero constante es el nombre de la funcion. Por el solo hecho de definir una funcion, el cargador del ejecutable, gratis, realiza esta asignacion para ti. Por ejemplo, para la definición

Código C:
Ver original
  1. void f() {}

f es un puntero constante, que guarda la dirección de memoria donde la función está y es entonces posible pasar f sin parentesis a una funcion que espera recibir un puntero a una funcion.

En el caso de métodos en C++ (o si quieres tomarlo asi, "funciones" al interior de una clase), ellos cumplen casi lo mismo.
Los nombres guardan direcciones de memoria, pero en realidad solo guardan un desplazamiento tomado desde el comienzo del objeto.

Si un objeto de una clase tiene un método dentro, este método (la dirección de memoria), está en la dirección del objeto + el desplazamiento del método.

Otro objeto de la misma clase compartirá con el anterior objeto el desplazamiento del método, pero no compartirá la dirección de comienzo del objeto. Para este 2do objeto, la dirección del método sera la dirección del objeto 2 + el mismo desplazamiento.

Entonces, cuando se trata de que una función o método reciba un método de otra clase, no es suficiente recibir la "dirección de memoria", pues solo estás recibiendo el desplazamiento, necesitas un objeto para poder calcular la dirección definitiva.

Si el método es static, estos se comportan igual que las funciones globales, pues su definición es solo 1 para todos los objetos de la misma clase.

La sintaxis de los punteros a métodos (que guardan ese desplazamiento) es un poco mas complicada, pero revísala solo si la necesitas. Si te sirve la definición de las funciones globales, quédate con esa.
__________________
Visita mi perfil en LinkedIn

Última edición por CalgaryCorpus; 03/02/2014 a las 14:28
  #5 (permalink)  
Antiguo 03/02/2014, 15:22
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: Usar un método que tiene otro método como argumento

Fenomenal. Muchísimas gracias por la respuesta.
Ahora entiendo el por qué.

Por cierto, ahora que me lo has explicado bien claro, termino de entender la explicación que se describe en el post al que enlazo de StackOverflow.
En este post, una respuesta ahonda en ese sentido, y dice que la forma sería crear un objeto al cual poderle aplicar el método del cuerpo de la función....al final esta mañana había investigado un poco por ahí y ya he visto que se trata de una función lambda (me refiero en todo momento al enlace que cito en mi primer post)

Ya sólo por curiosidad...¿esa es otra forma válida de enfocar el tema?

Cuando te aburras de mi me lo dices

Gracias de nuevo
  #6 (permalink)  
Antiguo 03/02/2014, 20:09
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: Usar un método que tiene otro método como argumento

¿Curiosidad respecto a lambdas?

Sugiero leer : http://goo.gl/gkCpvq
__________________
Visita mi perfil en LinkedIn
  #7 (permalink)  
Antiguo 04/02/2014, 04:09
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: Usar un método que tiene otro método como argumento

Genial, gracias por todo.
Entre tu explicación, esta que he encontrado, de un blog donde el autor es un borde pero muy divertido: http://bitbangers.wordpress.com/2009...ros-a-metodos/
y de los chicos de cconclase (en su momento seguí este curso, lo que pasa es que este capítulo pasó ya sin pena ni gloria para mi): http://c.conclase.net/curso/?cap=041#inicio

ya lo tengo todo claro.

Marco como solucionado y muchas gracias de nuevo.

Etiquetas: funcion, usar
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 12:46.