In which cases are the callback
functions used?
It is a question too broad to be answered in a concrete way, so it is best to give a broad answer: when necessary.
- The design pattern Visitor can be implemented with callbacks (although also can be implemented without them).
- Event response functions are usually implemented by callbacks.
Can they be used in classes?
Sure. Like any other data, a callback can be a member of a class, having these functions:
int suma (int a, int b) { return a + b; }
int resta (int a, int b) { return a - b; }
int multiplica(int a, int b) { return a * b; }
int divide (int a, int b) { return a / b; }
And this class that contains a callback :
class Clase
{
int (callback*)(int, int);
public:
Clase(int (operación*)(int, int)) : callback(operación) {}
int operar(int a, int b) { return callback(a, b); }
};
We can do the following:
Clase a(suma), b(resta);
std::cout << a.operar(1, 2) << '\n'; // muestra 3
std::cout << b.operar(1, 2) << '\n'; // muestra -1
Do they work in a similar way as in javascript ?
No. There are many differences between JavaScript and C ++ functions:
- JavaScript is a language of dynamic typing .
- JavaScript functions accept a number of undetermined parameters.
- JavaScript functions can be used as functions or as objects.
- Creating a function with
new
, it will act as a class, the this
of the created object will point to itself and the return value of the function is discarded.
- Creating a function without
new
the this
points to the global scope (which in browsers will be the object window
) and the return value can be captured by anyone who calls the function.
How is a function passed by means of a parameter?
We have seen it two sections ago:
int funcion_que_recibe_una_funcion(int (*parametro)(int, int), int a, int b)
{
return parametro(a, b);
}
Since C ++ is a language of strong typing , any parameter that points to a function needs to know all the types that are part of the function, that is: the type of return and the types of the parameters. Functions with different parameters and different types of return will have different types. So to create a variable of type function ( callback ) in C ++ we will do the following:
tipo_de_retorno (nombre_de_la_variable)( ... lista de parametros ... );
Therefore ...
// funcion que devuelve int y recibe dos int
int (a)(int, int);
// funcion que no devuelve ni recibe nada
void (b)();
// funcion que devuelve un string y recibe un puntero constante a char y un int
std::string (c)(const char *, int);
Normally this syntax is confusing, so we usually use typedef
:
typedef int (i_ii)(int, int);
typedef void (v_v)();
typedef std::string (s_ci)(const char *, int);
int funcion_que_recibe_una_funcion(i_ii *parametro, int a, int b)
{
return parametro(a, b);
}
void funcion_que_recibe_una_funcion(v_v *parametro)
{
parametro();
}
std::string funcion_que_recibe_una_funcion(s_ci *parametro, const char *a, int b)
{
return parametro(a, b);
}
Notice that we have added *
to indicate that we are receiving a function pointer; On the other hand the typedef
is usually considered confusing too, so the aliases were added from C ++ 11:
using i_ii = int(int, int);
using v_v = void();
using s_ci = std::string(const char *, int);
We can also use template aliases to make function pointers even simpler:
template <typename RETORNO, typename ... PARAMETROS>
using funcion = RETORNO(PARAMETROS ...);
int funcion_que_recibe_una_funcion(funcion<int, int, int> *parametro, int a, int b)
{
return parametro(a, b);
}
void funcion_que_recibe_una_funcion(funcion<void> *parametro)
{
parametro();
}
std::string funcion_que_recibe_una_funcion(funcion<std::string, const char *, int> *parametro, const char *a, int b)
{
return parametro(a, b);
}
And we can also add the pointer directly to the typedef
or alias:
typedef int (*p_i_ii)(int, int);
typedef void (*p_v_v)();
typedef std::string (*p_s_ci)(const char *, int);
using ap_i_ii = int(*)(int, int);
using ap_v_v = void(*)();
using ap_s_ci = std::string(*)(const char *, int);
template <typename RETORNO, typename ... PARAMETROS>
using puntero_a_funcion = RETORNO(*)(PARAMETROS ...);
When declaring the parameters of the function, what is its type?
The type of the parameters of the function does not change, a parameter of type T
will be of type T
always.