回调函数

回调函数或简称回调（callback），是计算机编程中对某一段可执行代码的引用，它被作为參數传递给另一段代码；预期这段代码将回调（执行）这个回调函数作为自己工作的一部份。这种执行可以是即时的，如在同步回调之中；也可以在后来的时间点上发生，如在异步回调之中。

编程语言以不同方式支持回调，经常将它们实现为子例程、lambda表达式、块或函数指针。

 使用 
回调的用途十分广泛。例如，假设有一个函数，其功能为读取配置文件并由文件内容设置对应的选项。若这些选项由散列值所标记，则让这个函数接受一个回调会使得程序设计更加灵活：函数的调用者可以使用所希望的散列算法，该算法由一个将选项名转变为散列值的回调函数实现；因此，回调允许函数调用者在运行时调整原始函数的行为。

回调的另一种用途在于处理信号或者类似物。例如一个POSIX程序可能在收到SIGTERM信号时不愿立即终止；为了保证一切运行良好，该程序可以将清理函数注册为SIGTERM信号对应的回调。

回调亦可以用于控制一个函数是否作为：Xlib允许自定义的谓词用于决定程序是否希望处理特定的事件。

 例子 
下列C语言代码描述了利用回调处理POSIX风格的信号（在本示例中为SIGUSR1）的过程。值得注意的是，在处理信号的过程中，调用printf(3)是不安全的。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sig(int signum)
{
    printf("Received signal number %d!\n", signum);
}

int main(int argc, char *argv[])
{
    signal(SIGUSR1, sig);

    pause();

    return 0;
}

系统调用pause(3)会导致这个例子不做任何有意义的事，但这样做可以给你充分的时间来给这个进程发送信号。（在类Unix系统上，可以调用kill -USR1 <pid>，其中<pid>代表该程序的进程号。运行之后，该程序应当会有反应。）

 实现 
回调的形式因程序设计语言而有差别。

 C、C++和Pascal允许将函数指针作为参数传递给其它函数。其它语言，例如JavaScript，Python，Perl和PHP，允许简单的将函数名作为参数传递。

 Objective-C中允许利用@selector关键字传递SEL类型的函数名。在实现中，SEL类型被定义为函数名字符串。

 在类似于C#与VB.NET的运用.NET Framework的语言中，提供了一种型别安全的引用封装，所谓的'委托'，用来定义包含类型的函数指针，可以用于实现回调。

 .NET语言中用到的事件与事件处理函数提供了用于回调的通用语法。

 函数式编程语言通常支持第一级函数，可以作为回调传递给其它函数，也可以作为数据类型存储或是返回给其它函数。

 某些语言，比如Algol 68，Perl，新版本的.NET语言以及多数函数式编程语言中，允许使用匿名的代码块（lambda表达式），用以代替在别处定义的独立的回调函数。

 在Apple或是LLVM的C语言扩展中，包含称为块的语言特性，可以作为函数的参数传递，作为回调的一种实现。

 在缺少函数类型的参数的面向对象的程序语言中，例如Java，回调可以用传递抽象类或接口来模拟。回调的接收者会调用抽象类或接口的方法，这些方法由调用者提供实现。这样的对象通常是一些回调函数的集合，同时可能包含它所需要的数据。这种方法在实现某些设计模式时比较有用，例如访问者模式，观察者模式与策略模式。

 C++允许对象提供其自己的函数调用操作的实现，即重载operator()。标准模板库和函数指针一样接受这类对象（称为函数对象）作为各种算法的参数。

 参见 
 续体传递风格

 事件驱动程式设计
 , C++的回调库
 控制反转

 参考资料 

 外部链接 
 Style Case Study #2: Generic Callbacks
 C++ Callback Solution
 Basic Instincts: Implementing Callback Notifications Using Delegates
 Implement Script Callback Framework in ASP.NET
 Implement callback routines in Java
 Interfacing C++ member functions with C libraries

Category:带有C代码示例的条目
Category:子程序