Смысл функции обратного вызова: функция, которая не вызывается программистом в любом месте своего кода, но вызывается из внешнего источника. Как правило, это означает ОС.
- Если внешний источник, вызывающий функцию, является аппаратным, вызываемая функция называется «службой обслуживания прерывания».
- Если внешний источник является программным обеспечением, вызываемая функция называется «функция обратного вызова».
Например, вы найдете множество функций обратного вызова в программировании Windows. Каждое графическое окно имеет функцию обратного вызова «WindowProc», которая получает вызов от ОС для каждого действия, происходящего в окне. Затем программисту необходимо написать функцию обратного вызова и обработать события, которые они интересуют. События, которые им не интересны, передаются обработчику по умолчанию (или базовому классу, если хотите).
Если программист хочет, чтобы что-то особенное произошло при щелчке мышью по окну, они могут перезаписать поведение по умолчанию щелчка мыши, заменив поведение по умолчанию собственным кодом. Таким образом, вы достигаете полиморфизма, даже в программах на C.
Пример из программирования с Windows:
LRESULT CALLBACK WindowProc (HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch(umsg)
{
case WM_LBUTTONDOWN:
do_something(); /* overwrite default behavior of a left mouse button click */
break; /* break = and then execute the default behavior afterwards */
case WM_RBUTTONDOWN:
do_something(); /* overwrite default behavior of a right mouse button click */
return 0; /* overwrite the default behavior entirely */
}
// execute default behavior for the event:
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
break
из оператора переключателя похож на обычное наследование: выполнить унаследованную функцию, а затем функцию базового класса. В то время как return 0;
похож на полиморфизм/виртуальный объект, поскольку наследуемый объект полностью перезаписывает поведение по умолчанию.
Sidenote: Так как функция обратного вызова вызывается из внешнего источника, а не саму программу, некоторые из тупее компиляторы будут делать предположения о том, что функция не вызывается и, следовательно, выполнять опасные оптимизации.
Например, если глобальная переменная «флаг» была изменена из WindowProc выше, а код в main()
полагается на «флаг», компилятор, возможно, оптимизирует код в main()
, так как считает, что «флаг» был никогда не использовались нигде.
Чтобы избежать этого неправильного поведения компилятора, рекомендуется всегда объявлять все переменные, разделяемые между функцией обратного вызова и остальной программой, как volatile
, что блокирует все оптимизации этой переменной.
Может быть дубликат http://stackoverflow.com/questions/142789/what-is-a-callback-in-c-and-how-are-they-implemented – Jay
2 примера: [библиотека стандартной библиотеки C qsort] (http://pubs.opengroup.org/onlinepubs/009695399/functions/qsort.html) и [Асинхронный ввод-вывод] (http://en.wikipedia.org/wiki/Asynchronous_I/O#Callback_functions) - Я не буду вдаваться в подробности, поскольку у меня такое чувство, что это задание. – pmdj
@Jay Я уже прошел через это. Я просил заявки не для реализации! Так же, как и Core Audio, мы говорим об этом! – Vikram