punteros - C++: puntero a funciones con número variable de argumentos
punteros en c++ definicion (4)
Estoy tratando de encontrar una manera de poder asignar un puntero a una función con un número diferente de argumentos.
Usted no puede Los punteros de función son específicos de una firma de función. Esto es completamente lógico: ¿cómo invocarías una función así? (Sí, C permite invocar funciones sin especificar en su declaración cuántos parámetros tiene la función, pero esto no funciona en C ++, ya que subvierte el sistema de tipos).
¿Son los functoides algo que debería mirar?
En general sí, pero no resuelven este problema.
Estoy tratando de encontrar una manera de poder asignar un puntero a una función con un número diferente de argumentos.
Tengo un bucle while que toma una serie de funciones diferentes como una declaración condicional, así que en lugar de escribir varios bucles while con exactamente el mismo código interno, me gustaría tener uno con un puntero a función. Todas las funciones son de formato bool f(...)
. Creo que un código ilustrará mejor lo que quiero decir:
int a, b, c, d;
MyClass* my_class;
typedef bool (MyClass::*my_fun_t)();
my_fun_t my_fun;
if (condition1)
my_fun = &MyClass::function_one();
else if (condition2)
my_fun = &MyClass::function_two(a, b);
else if (condition3)
my_fun = &MyClass::function_three(a, b, c);
else if (condition4)
my_fun = &MyClass::function_four(a, b, c, d);
while ((my_class->*my_fun)())
{ ... }
Ahora bien, obviamente esto no funciona porque las funciones tienen diferentes firmas. ¿Es posible que funcione de manera similar? ¿Son los functoides algo que debería mirar?
Desea std::function
, un objeto de función polimórfica y std::bind
para crear objetos de función mediante el enlace de argumentos a los parámetros de otros functores.
Si no puedes usar C ++ 11, boost::function
y boost::bind
son equivalentes, aunque un poco más restrictivos.
std::function<bool()> my_fun;
if (condition1)
my_fun = std::bind(&MyClass::function_one, my_class);
else if (condition2)
my_fun = std::bind(&MyClass::function_two, my_class, a, b);
else if (condition3)
my_fun = std::bind(&MyClass::function_three, my_class, a, b, c);
else if (condition4)
my_fun = std::bind(&MyClass::function_four, my_class, a, b, c, d);
while (my_fun())
{ ... }
Esto funciona para mí:
#include <iostream>
#include <cstdarg>
using namespace std;
class MyInterface
{
public:
virtual bool func(int argc, ...) = 0;
};
class MyImpl : public MyInterface
{
public:
virtual bool func(int argc, ...);
};
bool MyImpl::func(int argc, ...)
{
va_list varargs;
va_start(varargs,argc);
cout << "Arguments passed:" << endl;
for(int i = 0; i < argc; ++i)
{
// expect double values
double val = va_arg(varargs,double);
cout << val << endl;
}
va_end(varargs);
return true;
}
typedef bool (MyInterface::*MyFunc)(int, ...);
int main() {
MyImpl impl;
MyInterface* interface = &impl;
MyFunc pfunc = &MyInterface::func;
if(!(interface->*pfunc)(2,double(3.14),double(2.72)))
{
return 1;
}
return 0;
}
Salida:
Arguments passed:
3.14
2.72
Obviamente, PUEDE declarar y usar los punteros de función para las funciones (miembro) que usan argumentos variables.
Podría usar std::function<>
y std::bind()
.
#include <functional>
using std::placeholders::_1;
typedef std::function<bool(MyClass&)> my_fun_t;
my_fun_t my_fun;
if (condition1)
my_fun = std::bind(&MyClass::function_one, _1);
else if (condition2)
my_fun = std::bind(&MyClass::function_two, _1, a, b);
else if (condition3)
my_fun = std::bind(&MyClass::function_three, _1, a, b, c);
else if (condition4)
my_fun = std::bind(&MyClass::function_four, _1, a, b, c, d);
while (my_fun(my_class)) { ... }
Estos asumen que usarás C ++ 11. Si no puede usar C ++ 11 pero puede usar TR1, reemplace todos std::
con std::tr1::
. También hay una implementación de Boost .