Acerca de...
El equipo
Encuestas
Política de privacidad
WinTablets

Encuesta

¿Cual crees que triunfará?

Ver Resultados

Cargando ... Cargando ...

últimas entradas importantes

Categorías

Entradas recientes

Archivos

23
Jul 2015
C++DesarrolloMultiplataformarfogdev

Pasar punteros a método miembro con C++11

Desde niños siempre hemos querido pasar de forma fácil un puntero a método miembro a algún otro método para luego ejecutar ese método. Aquí os voy a explicar la forma de hacerlo al estilo de C++11 con el apoyo de la biblioteca estándar de C++.

¿Cómo? ¿Que no sabes de qué hablo? Pues entra porque primero te voy a explicar qué es eso de método miembro, puntero y por qué es necesario hacer algo así. Y para más inri, no vas a ver ni un solo puntero de verdad.

Es la nueva moda en C++: usar punteros pero sin que se vean, dejando toda la complejidad al compilador y a las bibliotecas, como debe ser. Para los que dicen que C++ es muy complejo (que lo es, pero por otros motivos).

Que levante la mano quien sepa qué es una función de callback. Vale.

Supongamos por un momento que necesitamos que una parte de nuestro programa informe a otra cuando ocurra algo en otra parte. Vamos a suponer que estás guardando en disco un fichero muy grande, o uno muy pequeño pero que está en una red muy lenta. Si no quieres bloquear la interfaz, lo normal es que lances el guardado en un hilo independiente y, por ejemplo, desactives algunos botones de tu interfaz como la opción de guardar porque ya estás guardando.

De ese modo el usuario puede continuar editando su texto mientras este se va guardando poco a poco. Pero cuando el guardado del fichero termine, quieres que esa parte del código avise a donde controlas la activación/desactivación de los elementos de la interfaz para cambiar valores.

Podrías decir que bien puedes hacerlo desde el mismo hilo en donde estás guardando el fichero, pero eso se salta algunos patrones y no es factible en las interfaces modernas porque la interfaz no se puede tocar por otro hilo que no sea el principal.

Además, la activación o no de algunos botones podría depender de otras opciones, como que el usuario no haya tocado el texto, por lo tanto la mejor forma es disponer de un método “activador” que verifique toda la situación.

¿Cómo hago eso? Pues cuando lances tu trabajo de guardado, pasas un puntero al método que será llamado para cambiar la interfaz, y cuando el trabajo haya terminado, tu código lo ejecutará.

En C la cosa es fácil, ya que un callback no es más que una dirección de memoria, pero en C++, cuando hay clases de por medio, la cosa se complica porque un puntero a un método miembro son dos direcciones de memoria. La primera apunta al objeto en memoria, y la segunda al método en cuestión.

No vamos a entrar en detalles sobre la necesidad de que sea así. En este momento asumiremos que lo es.

Por lo tanto una solución chapucera sería pasar dos punteros: el del método a ejecutar y el del objeto sobre el que se va a ejecutar, que suele ser this. Pero la sintaxis para hacer eso es muy barroca y tendente a errores.

Por lo tanto, C++11 y su biblioteca estándar, implementan una forma bastante sencilla de hacerlo. Fijaos en la captura.

c1

Las dos primeras líneas definen unos nombres para facilitar la sintaxis. Luego la clase Test contiene dos métodos normales y corrientes que reciben uno y dos enteros. Ejecutando esos métodos se nos imprimen los numero pasados.

Fijémonos en los dos métodos siguientes, los que se llaman OneParamsPointer y TwoParamsPointer, que reciben un puntero a método y lo ejecutan.

Ya en main() tenemos el busilis de la cuestión. El enlace se realiza mediante la función bind(), que toma un puntero al método, una referencia a la clase sobre la que se quieren ejecutar los métodos, y un placeholder para cada uno de los parámetros.

Los valores _1 indican el primer parámetro, _2 el segundo, etc., por lo que en principio se podría cambiar el orden del paso de los mismos en el caso de que fueran del mismo tipo (como lo son aquí), pero mejor no liarla más.

El resultado de la ejecución es el esperado:

c2

¿Vosotros habéis visto algún puntero? Yo tampoco. :-)

 

Por RFOG | 8 Comentarios | Enlaza esta entrada
contacto@wintablet.info tema WinTablet.info por Ángel García (Hal9000)