Duda sobre sintaxis: Un argumento que hace referencia a una funcion...

Iniciado por digimikeh, 17 Abril 2019, 04:33 AM

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

digimikeh

Hola!..

Estoy practicando Unreal y QT Creator, en ambos he visto esta sintaxis:


Código (cpp) [Seleccionar]


void unaFuncionCualquiera(){

    unaClase.unMetodo(&ClaseA::unaFuncionB);  //este argumento..

}


void ClaseA::unaFuncionB(){
    //hacer algo
}


En Unreal se manipulan los controles de esta forma.
En QT se conecta un botón con una función...

Entiendo el efecto que tiene, pero que tipo de parámetro es?,, como se denomina este tipo de parámetros?



Saludos y gracias.
Dungeons & dragons;
dragons.Attack();

MAFUS

Son punteros a funciones. Es una forma de hacer que una función pueda hacer muchas cosas diferentes, dependiendo del método o función que se les pase.
Es una forma de hacer las cosas genéricas.
Sólo importante que la función o método que se le pase cómo parámetro coincida con la que se espera.

Un ejemplo en C:
#include <stdio.h>

int suma(int a, int b) {
   return a + b;
}

int resta(int a, int b) {
   return a - b;
}

int calcular(int (*funcion)(int, int), int a, int b) {
   return funcion(a, b);
}

int main () {
   int a = 3;
   int b = 2;

   printf("%d + %d = %d\n", a, b, calcular(suma, a, b));
   printf("%d - %d = %d\n", a, b, calcular(resta, a, b));
}


Esto devuelve:
Citar3 + 2 = 5
3 - 2 = 1

digimikeh

Ok, entiendo!..gracias..
Entonces las funciones también estarían ocupando un espacio en la memoria?
Dungeons & dragons;
dragons.Attack();

Loretz

CitarEntonces las funciones también estarían ocupando un espacio en la memoria?

Los punteros a funciones sí, pero en tu caso no tienes un puntero a función sino un "puntero a función miembro", que es diferente.

Un puntero a función miembro no apunta a nada hasta que no se cree el objeto y se defina a qué función apuntará, y como es "implementation defined", dependerá del compilador si lo implementa como un puntero u otra cosa.

La sintaxis es un poco compleja; un ejemplo simple ya lo muestra:

Código (cpp) [Seleccionar]
#include <iostream>

class UnaClase {
public:
    void unMetodo()
    {
        std::cout << "UnaClase::unMetodo()\n";
    }
};

void unaFuncion(UnaClase* p, void(UnaClase::* pmf)())
{
    (p->*pmf)();  ///< recien aqui se define a que funcion de que objeto apunta el "puntero a funcion miembro" (pmf)
}

int main()
{
    UnaClase unaClase;
    unaFuncion(&unaClase, &UnaClase::unMetodo);  ///< debe invocarse con el objeto ademas del "puntero a funcion miembro";
                                                 ///< y si la funcion miembro toma parametros, tambien habra que pasarselos.
}



digimikeh

Se ve un tanto complejo pero voy entendiendo.

Bajo que circunstancias se puede usar puntero a función y método miembro?

Gracias
Dungeons & dragons;
dragons.Attack();

Loretz

CitarBajo que circunstancias se puede usar puntero a función y método miembro?

En C++ hay funciones pero no "métodos", algunas veces se dice así por costumbre adquirida en otros lenguajes, pero en C++ sólo hay funciones, algunas serán "member functions" y otras no, pero no hay más.

Y francamente no tengo una respuesta de esas iluminadoras, pero creo que en general se usa un puntero a función miembro más o menos de la manera en que se usa un puntero a función.

Como has estado viendo, QT Creator implementa sus event handlers usando punteros a funciones miembro.

Muchas veces puede usarse otro mecanismo para conseguir el mismo resultado, comúnmente apelando a las funciones virtuales.

También, en la biblioteca estándar están std::function que puede inicializarse con una función miembro, y está std::bind, que devuelve un function object que puede invocar una función (miembro o no), con sus parámetros de llamada asociados.

Aunque no encuentro un ejemplo simple donde pueda mostrarse fácilmente un uso indiscutible, se puede ver su uso en la aplicación del "Open-close principle" https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle; por ejemplo, en "The Safe Bool Idiom": https://www.artima.com/cppsource/safebool2.html



digimikeh

Dungeons & dragons;
dragons.Attack();