如何从函数中创建函数指针,并在c++中固定了某些参数

How to create a function pointer from a function with certain parameters fixed in C++

本文关键字:函数 参数 c++ 创建 指针 并在      更新时间:2023-10-16

假设我想调用一个函数f,它请求一个类型为

的函数指针
int (*foo)(int)
函数类似于
double f( int (*foo)(int))

我有一个这样做的函数,但它接受另一个对象。

int bar(int, MyClass*)

这个对象是在运行时创建的,比如

int main()
    // ... read some file / input
    MyClass myclass = MyClass(input);
    // Now pass the function pointer
    double retval = f( bar( int, &myclass))

有没有办法实现最后一行?我正在寻找一个没有全局对象的答案。

No.

你对函数f有影响吗?在c++中,这将通常是一个可以接受任何可调用对象的模板,或者它将使用一个简单的接口,您可以从中推导。在这两种在这种情况下,您将定义一个可以包含附加数据的类。像这样使用指向函数的指针是非常糟糕的设计。

编辑以说明f不能被修改的事实:

既然你不能修改f,我能想到的唯一解决方案是使用某种全局变量和转发函数:

int bar(int i, MyClass * mc);
namespace bar_parameters
{
    MyClass * mc = 0;
}
int binded_bar(int i)
{ 
    return bar(i, bar_parameters::mc);
}
int main()
{
    MyClass myclass(input);
    bar_parameters::mc = &myclass;
    double retval = f(binded_bar);
}

这是相当丑陋的,然而…


不能绑定函数的形参。但是,对于functor(函数对象)来说,这是可能的。

您需要做的第一件事是修改f的参数,使其成为一个函数对象,如std::functionboost::function,而不是函数指针:

double f(std::function<int (int)> foo);

这个函数既可以与函数指针一起使用,也可以与具有正确签名的函子一起使用。

在此之后,您可以使用绑定方法,如std/boost::bind(或c++ 03中的bind1st/bind2nd):
double retval = f(std::bind(bar, _1, &myclass));

如果你不能访问Boost或c++ 0x,你可以使用通常的技术,包括制作参数模板,以便接受任何可调用的实体(函数指针和函子):

template <typename Func>
double f(Func foo);

这种方法的缺点是,函数的签名只能通过您在f中使用它的方式来强制执行。

要绑定第二个参数,然后可以使用ptr_fun将函数指针转换为函数对象,并使用bind2nd实际绑定参数:

double retval = f(std::bind2nd(std::ptr_fun(bar), &myclass));

您可以通过使用Boost.Bind实现类似的功能。这现在是c++标准的一部分,甚至可能已经在您的编译器中可用。注意Boost。Bind仍然要求您修改f的签名。如果这是不可能的,你可以这样做

MyClass* _only_to_be_used_by_ugly;
int ugly(int i) {
  return bar(i, _only_to_be_used_by_ugly)
}
int main() {
  _only_to_be_used_by_ugly = MyClass(input);
  double retval = f(ugly);
}

但我是第一个反对类似方法的人。

在您的情况下,您将不得不做一些邪恶的事情,如:

MyClass* g_myclass = 0;
int my_f(int i) {
    return bar(i, g_myclass);
}
int main()
    // ... read some file / input
    MyClass myclass = MyClass(input);
    // Now pass the function pointer
    g_myclass = &myclass;
    double retval = f(&my_f);
    g_myclass = 0; // no longer needed (you hope).
    ...
}

YMMV。如果你传递的函数指针被保留在某个地方,并在以后再次使用,那么你将陷入麻烦。在这种情况下,您需要有一个静态函数列表和一个指向MyClass的指针全局数组,并根据需要从该列表中分配/释放。可以使用递归模板元程序生成这些函数。不太好,但可能。

或者,找出如何生成所需的汇编程序来执行绑定并在汇编指令中编码MyClass指针。然后在堆上分配该函数。不是很便携,但也应该是可行的。我从来没有尝试过,所以不能保证它会工作或容易做到。代码看起来也很难看。