使用回调(在非事件驱动程序中)的优点

时间:2018-11-22 23:11:05

标签: c callback

我正在研究以下回调示例: https://en.wikipedia.org/wiki/Callback_(computer_programming)

#include <stdio.h>
#include <stdlib.h>

/* The calling function takes a single callback as a parameter. */
void PrintTwoNumbers(int (*numberSource)(void)) {
    int val1 = numberSource();
    int val2 = numberSource();
    printf("%d and %d\n", val1, val2);
}

/* A possible callback */
int overNineThousand(void) {
    return (rand()%1000) + 9001;
}

/* Another possible callback. */
int meaningOfLife(void) {
    return 42;
}

/* Here we call PrintTwoNumbers() with three different callbacks. */
int main(void) {
    PrintTwoNumbers(&rand);
    PrintTwoNumbers(&overNineThousand);
    PrintTwoNumbers(&meaningOfLife);
    return 0;
}

我了解所有功能。但是,我想知道除了减少一行,这样做的好处是什么?

PrintTwoNumbers(&overNineThousand);

不仅仅是像常规函数一样使用它们:

int a = overNineThousand();
PrintTwoNumbers(a);

谢谢!

3 个答案:

答案 0 :(得分:2)

这是所谓的Higher Order Function的简单例子。

在此特定示例中,它不是很有用。您说对了,直接传递数据会更容易。

这是一种允许对函数进行泛化的技术,并且在正确使用时对减少代码重复非常有帮助。

一个典型的示例是map函数,该函数可以转换列表:

var arr = [1, 2, 3];
var newArr = arr.map(x => x + 1); // Pass a function that adds one to each element

print(newArr); // Prints [2, 3, 4]

没有高阶函数,您每次要转换列表时都必须编写包含map的相同循环代码。如果要在其他位置的每个元素上添加2,该怎么办?还是每个乘以5?通过传递一个函数,您可以告诉它如何转换每个项目,而不必担心迭代。

如评论中所述,另一个示例是排序功能。它们允许您传递确定排序顺序的函数。如果没有该功能,则需要为每种不同的排序顺序和元素类型编写新的排序功能。


对不起,我无法用C回答这个问题。我了解您发布的代码中发生了什么,但是我不了解C,因此无法提供使用HOF的良好示例代码。

答案 1 :(得分:0)

如果问题只是计算一个元素,那么是的,回调不是很有用。

现在,如果我们认为函数可能需要以(非确定性的)方式多次调用回调,那么就需要回调。

通常,C语言中最常见的回调之一是qsort,其中回调是必需的。

答案 2 :(得分:0)

至少有两种情况下回调是有用的:

  • 在某些数据上重复执行任务的功能。注释中给出的示例很好:将比较函数作为回调传递给sort函数是一个有用的回调的很好示例。
  • 枚举函数。这是在您向图书馆索取对象列表并且要对每个对象进行操作时。您会将回调传递给枚举函数。例如:EnumWindows