C++:如何将函数(不知道其参数)传递给另一个函数?

Nin*_*nja 9 c++ pointers function-pointers timer parameter-passing

我正在尝试创建一个函数来存储和重复另一个函数,该函数作为特定时间或给定重复的参数给出.但是当你想要将函数作为参数传递时,你必须事先知道它的所有参数.如果我想将函数作为一个参数传递,而将参数作为另一个参数传递,我该怎么办?

void AddTimer(float time, int repeats, void (*func), params); // I know params has no type and that (*func) is missing parameters but it is just to show you what I mean
Run Code Online (Sandbox Code Playgroud)

提前致谢

Dav*_*eas 15

您可以做的最好的事情是使用std::functionboost::function作为参数,与std::bind或一起使用boost::bind函数绑定参数:

void foo() { std::cout << "foo" << std::endl; }
void bar( int x ) { std::cout << "bar(" << x << ")" << std::endl; }
struct test {
   void foo() { std::cout << "test::foo" << std::endl; }
};
void call( int times, boost::function< void() > f )
{
   for ( int i = 0; i < times; ++i )
      f();
}
int main() {
   call( 1, &foo );                   // no need to bind any argument
   call( 2, boost::bind( &bar, 5 ) );
   test t;
   call( 1, boost::bind( &test::foo, &t ) ); // note the &t
}
Run Code Online (Sandbox Code Playgroud)

请注意,传递完全通用的函数指针存在一些固有的错误:你如何使用它?调用函数的主体如何能够传递未定义数量的未知类型的参数?这就是bind模板解析的内容,它们创建了一个类函数,它存储函数指针(具体函数指针)以及调用时要使用的参数的副本(注意&t示例中的指针而不是复制对象).结果bind是一个可以通过已知接口调用的仿函数,在这种情况下,它可以绑定在a中function< void() >并且不带参数调用.


Ste*_*sop 3

就现代 C++ 而言,dribeas 的答案是正确的。

出于兴趣,还有一个来自 C 世界的简单低技术解决方案,就其本身而言,可以在 C++ 中运行。不要允许任意参数,而是将函数定义为void (*func)(void*),并创建“params” void*。然后,调用者的工作是定义一些包含参数的结构,并管理其生命周期。通常调用者还会为真正需要调用的函数编写一个简单的包装器:

void myfunc(int, float); // defined elsewhere

typedef struct {
    int foo;
    float bar;
} myfunc_params;

void myfunc_wrapper(void *p) {
    myfunc_params *params = (myfunc_params *)p;
    myfunc(params->foo, params->bar);
}

int main() {
    myfunc_params x = {1, 2};
    AddTimer(23, 5, myfunc_wrapper, &x);
    sleep(23*5 + 1);
}
Run Code Online (Sandbox Code Playgroud)

在实践中,您希望“触发后不管”计时器,因此,如果您使用此方案,您可能还需要一种方法,让计时器在所有触发完成后设法释放用户数据指针。

显然,这具有有限的类型安全性。原则上应该不重要,因为无论谁提供函数指针和用户数据指针,确保它们匹配都不会有太大困难。当然,在实践中,人们会找到编写错误的方法,以及责怪你的方法,因为他们的编译器没有告诉他们这些错误;-)