Концепция обратного вызова имеет много приложений. Например, некоторые алгоритмы (функции) в качестве подзадачи имеют задачу вычисления хеш-значения от строки. В аргументах при запуске алгоритма (функции) удобно задавать, какую именно функцию использовать для вычисления хеш-значений.
Другой пример алгоритма, которому естественно передавать в аргументе функцию, — алгоритм обхода какого-либо хранилища объектов с применением некоторого действия к каждому объекту. Обратный вызов может выступать в роли этого действия (алгоритма).
Техника программирования обратного вызова в языках программирования, подобных языку C, проста. При вызове основной функции ей просто передаётся указатель на функцию обратного вызова. Классическим примером является функция qsort из библиотеки stdlib. Эта функция позволяет отсортировать массив блоков байт одинаковой длины. В качестве аргументов она получает адрес первого элемента массива, количество блоков в массиве, размер блока байт, и указатель на функцию сравнения двух блоков байт. Эта функция сравнения и есть функция обратного вызова в данном примере:
`#include
// функция сравнения целых чисел по модулю
int compare_abs(const void *a, const void *b) {
int a1 = *(int*)a;
int b1 = *(int*)b;
return abs(a1) - abs(b1);
}
int main() {
int size = 10;
int m[size] = {1, -3, 5, -100, 7, 33, 44, 67, -4, 0};
// сортировка массива m по возрастанию модулей
qsort(m, size, sizeof(int), compare_abs);
return 0;
}`
Об обратном вызове можно думать как о действии, передаваемом некоторой основной процедуре в качестве аргумента. И это действие может рассматриваться как:
подзадача и использоваться для обработки данных внутри этой процедуры;
«телефонная связь», используемая для того, чтобы «связываться» с тем, кто вызвал процедуру, при наступлении какого-то события (англ. callback дословно переводится как «звонок обратно»).
Показанный выше пример как раз соответствует первому случаю. Случай, когда обратный вызов используется как «телефонная связь», отражает код, где задаётся функция обработки определённого сигнала:
`#include
#include
volatile sig_atomic_t br = 1;
void sig(int signum)
{
br=0;
}
int main(int argc, char *argv[])
{
signal(SIGINT, sig);
printf("Press break keyboard key combination to stop the program\n");
while(br);
printf("Received SIGINT, exit\n");
return 0;
}`
В некоторых языках программирования, таких как Common Lisp, Erlang, Scheme, Clojure, PHP, JavaScript, Perl, Python, Ruby и других, есть возможность конструировать анонимные (не именованные) функции и функции-замыкания прямо в выражении вызова основной функции, и эта возможность широко используется.
В технологии AJAX при выполнении асинхронного запроса к серверу необходимо указывать функцию обратного вызова, которая будет вызвана, как только придёт ответ на запрос. Часто эту функцию определяют «прямо на месте», не давая ей никакого определённого имени:
`new Ajax.Request('
example.com/do_it',
{
method: 'post',
onSuccess: function(transport) { // функция, вызываемая
window.alert("Done!"); // при успешном выполнении запроса
}, //
onFailure: function() { // функция, вызываемая
window.alert("Error!"); // при ошибке выполнения запроса
}
});`