C++ 使用函数作为参数

40
假设我有一个名为的函数
void funct2(int a) {

}


void funct(int a, (void)(*funct2)(int a)) {

 ;


}

这个函数应该怎么正确地调用?我需要设置什么才能让它正常工作?

这个问题可能会有所帮助:https://dev59.com/9nVD5IYBdhLWcg3wWKLc - Jim
1
你有两个函数,你在调用哪一个时遇到了问题?请注意,你通过使用相同名称的指向函数的参数将funct2隐藏在funct中,因此你必须完全限定funct2才能直接从funct内部调用它。 - CB Bailey
7
没问题,因为我们都知道C++就是C。欢迎来到CloseOverflow。如果您使用的是C++11,这里有一个好的阅读材料:https://dev59.com/MWQo5IYBdhLWcg3wXeb5 -- 避免使用指针传递函数可以提高可读性。 - greenoldman
7
这怎么能算是一个有关C语言的重复问题呢?C++也许会提供(或者已经提供)一种不同的方法。请问您需要翻译其他内容吗? - pooya13
1
@pooya13 这不是重复的。在C++中,有其他传递函数作为参数的方法,这在C语言中是不可能的(例如使用函数对象)。 - Anderson Green
显示剩余2条评论
5个回答

38

通常出于可读性的考虑,您可以使用typedef来定义自定义类型,如下所示:

typedef void (* vFunctionCall)(int args);

当定义此typedef时,您希望函数原型的返回参数类型(在本例中为void类型)作为typedef标识符的前缀,并将原型参数跟随其后(在本例中为"int args")。

在将此typedef用作另一个函数的参数时,您将定义您的函数如下(此typedef几乎可以像任何其他对象类型一样使用):

void funct(int a, vFunctionCall funct2) { ... }

然后像普通函数一样使用,如下:

funct2(a);

那么一个完整的代码示例会像这样:

typedef void (* vFunctionCall)(int args);

void funct(int a, vFunctionCall funct2)
{
   funct2(a);
}

void otherFunct(int a)
{
   printf("%i", a);
}

int main()
{
   funct(2, (vFunctionCall)otherFunct);
   return 0;
}

并且会打印出:

2

11
自C++11起,为了提高可读性,更好的选择是使用using vFunctionCall = void (*)(int args);。甚至更好的选择是使用std::function - Frederico Pantuzza
4
不需要进行任何铸造。 - HAL9000
1
自从C++11以来,我更喜欢看到std::function<>。 - Goswin von Brederlow
2
@GoswinvonBrederlow std::function<void(int)>void (*)(int args) 做的事情 多得多,因此对于平台来说更难进行优化。 - Caleth

36
另一种方法是使用函数库。
这里有一个例子,我们将在`funct`中使用`funct2`:
#include <functional>
#include <iostream>

void displayMessage(int a) {
    std::cout << "Hello, your number is: " << a << '\n';
}

void printNumber(int a, std::function<void (int)> func) {
    func(a);
}

int main() {
    printNumber(3, displayMessage);
    return 0;
}

输出:

Hello, your number is: 3

1
也许你应该演示一下如何调用这个函数。 - JVE999
3
尽量不要使用using namespace std,因为这是一种不好的编程习惯:https://dev59.com/D3M_5IYBdhLWcg3wQQ3w?rq=1 - Overt_Agent
我可以使用这种语法将类A的公共方法传递给类B的构造函数吗?如果可以,怎么做? - tickietackie

1
基本的C++方法是使用std::function,它类似于函数类型,例如在函数式语言中的类型int -> double。它实际上不是一个类型,而是一个类模板,类实例可以持有可调用的函数,但在使用时,将其视为函数类型是很有用的。
例如,这个函数接受int并返回double
double halve(int x)
{
    return x / 2;
}

现在你可以分配函数本身(函数作为一等公民):
std::function<double(int)> f = halve; // can store a lambda too

你可以将它作为参数类型或返回类型传递。例如:
double call_f(std::function<double(int)> f, int x)
{
    return f(x);
}

另一个选择是使用模板。编译器会自动推断类型并生成正确类型的代码。请参阅这个比较

-1
一个更详细和普遍(非抽象)的例子
#include <iostream>
#include <functional>
int Add(int a, int b)
{
    return a + b;
}
int Mul(int a, int b)
{
    return a * b;
}
int Power(int a, int b)
{
    while (b > 1)
    {
        a = a * a;
        b -= 1;
    }
    return a;
}
int Calculator(std::function<int(int, int)> foo, int a, int b)
{
    return foo(a, b);
}
int main()
{
    cout << std::endl
         << "Sum: " << Calculator(Add, 1, 2);
    cout << std::endl
         << "Mul: " << Calculator(Mul, 1, 2);
    cout << std::endl
         << "Power: " << Calculator(Power, 5, 2);
    return 0;
}

1
我觉得这个答案与此答案相比,没有足够的价值来证明它应该是一个单独的答案。 - starball

-3

请检查这个

typedef void (*funct2)(int a);

void f(int a)
{
    print("some ...\n");
}

void dummy(int a, funct2 a)
{
     a(1);
}

void someOtherMehtod
{
    callback a = f;
    dummy(a)
}

那是C,不是C++。 - Michał Leon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接