Функция обратного вызова — это функция, которая является аргументом, а не параметром другой функции. Вторую функцию можно назвать основной. Таким образом, задействованы две функции: основная функция и сама функция обратного вызова. В списке параметров основной функции присутствует объявление функции обратного вызова без ее определения, как и объявления объекта без присваивания. Основная функция вызывается с аргументами (в main ()). Одним из аргументов в вызове основной функции является эффективное определение функции обратного вызова. В C ++ этот аргумент является ссылкой на определение функции обратного вызова; это не настоящее определение. Сама функция обратного вызова фактически вызывается в определении основной функции.
Базовая функция обратного вызова в C ++ не гарантирует асинхронного поведения в программе. Асинхронное поведение — реальное преимущество схемы функции обратного вызова. В схеме асинхронной функции обратного вызова результат основной функции должен быть получен для программы до того, как будет получен результат функции обратного вызова. Это возможно сделать в C ++; однако в C ++ есть библиотека под названием future, которая гарантирует поведение схемы асинхронной функции обратного вызова.
В этой статье объясняется базовая схема функции обратного вызова. Во многом это связано с чистым C ++. Что касается обратного вызова, также объясняется основное поведение будущей библиотеки. Базовые знания C ++ и его указателей необходимы для понимания этой статьи.
Содержание статьи
- Базовая схема функции обратного вызова
- Синхронное поведение с функцией обратного вызова
- Асинхронное поведение с функцией обратного вызова
- Базовое использование будущей библиотеки
- Заключение
Схема базовой функции обратного вызова
Схема функции обратного вызова требует основной функции и самой функции обратного вызова. Объявление функции обратного вызова является частью списка параметров основной функции. Определение функции обратного вызова указывается в вызове функции основной функции. Функция обратного вызова фактически вызывается в определении основной функции.. Следующая программа иллюстрирует это:
using namespace std;
int PrincipalFn (char ch [], int (* ptr) (int))
{
int id1 = 1;
int id2 = 2;
int idr = (* ptr) (id2);
cout
return id1;
}
int cb (int ID)
{
cout
return identif;
}
int main ()
{
int (* ptr) (int) = & cb;
char cha [] = «и»;
PrincipalFn (cha, cb);
return 0;
}
Результат:
основная функция : 1 и 2
Основная функция идентифицируется с помощью PrincipalFn (). Функция обратного вызова идентифицируется cb (). Функция обратного вызова определяется вне основной функции, но фактически вызывается внутри основной функции.
Обратите внимание на объявление функции обратного вызова как параметр в списке параметров объявления основной функции. Объявление функции обратного вызова — «int (* ptr) (int)». Обратите внимание на выражение функции обратного вызова, как и на вызов функции, в определении основной функции; туда передается любой аргумент для вызова функции обратного вызова. Оператор для этого вызова функции:
Где id2 — это аргумент. ptr является частью параметра, указателя, который будет связан со ссылкой на функцию обратного вызова в функции main ().
Обратите внимание на выражение:
В функции main (), которая связывает объявление (без определения) функции обратного вызова с имя определения той же функции обратного вызова.
Основная функция вызывается в функции main () как:
Где cha — строка, а cb — имя функции обратного вызова без каких-либо ее аргументов.
Синхронное поведение функции обратного вызова
Рассмотрим следующую программу:
using namespace std;
void PrincipalFn (void (* ptr) ())
{
cout
(* ptr) ();
}
void cb ()
{
cout
}
void fn ()
{
cout
}
int main ()
{
void (* ptr) () = & cb;
PrincipalFn (cb);
fn ();
return 0;
}
Результатом будет:
функция обратного вызова
видно
Здесь есть новая функция. Все, что делает новая функция, — это отображение вывода, «видимого». В функции main () вызывается основная функция, затем вызывается новая функция fn (). Выходные данные показывают, что был выполнен код для основной функции, затем был выполнен код для функции обратного вызова и, наконец, был выполнен код для функции fn (). Это синхронное (однопоточное) поведение.
Если бы это было асинхронное поведение, когда три сегмента кода вызываются по порядку, может быть выполнен первый сегмент кода, за которым вместо этого следует выполнение третьего сегмент кода перед выполнением второго сегмента кода.
Ну, функция fn () может быть вызвана из определения основной функции, а не из функции main (), следующим образом:
using namespace std;
void fn ()
{
cout
}
void PrincipalFn (void (* ptr) ())
{
cout
fn ();
(* ptr) ();
}
void cb ()
{
cout
}
int main ()
{
void (* ptr) () = & cb;
PrincipalFn (cb);
return 0;
}
Результатом будет:
замечена
функция обратного вызова
Это имитация асинхронного поведения. Это не асинхронное поведение. Это по-прежнему синхронное поведение.
Кроме того, порядок выполнения сегмента кода основной функции и сегмента кода функции обратного вызова можно поменять местами в определении основной функции.. Следующая программа иллюстрирует это:
using namespace std;
void PrincipalFn (void (* ptr) ())
{
(* ptr) ();
cout
}
void cb ()
{
cout
}
void fn ()
{
cout
}
int main ()
{
void (* ptr) () = & cb;
PrincipalFn (cb);
fn ();
return 0;
}
Теперь на выходе
основная функция
замечено
Это тоже имитация асинхронного поведения. Это не асинхронное поведение. Это все еще синхронное поведение. Истинное асинхронное поведение может быть получено, как описано в следующем разделе, или с помощью библиотеки в будущем.
Асинхронное поведение с функцией обратного вызова
Псевдокод для базового асинхронного Схема функции обратного вызова:
type cb (type output)
{
//операторы
}
тип PrincipalFn (тип input, type cb (тип output) )
{
//операторы
}
Примечание позиции входных и выходных данных в разных местах псевдокода. Входом функции обратного вызова является ее выход. Параметры основной функции — это входной параметр для общего кода и параметр для функции обратного вызова. С помощью этой схемы третья функция может быть выполнена (вызвана) в функции main () до того, как будет прочитан вывод функции обратного вызова (все еще в функции main ()). Следующий код иллюстрирует это:
using namespace std;
char * output;
void cb (char out [])
{
output = out ;
}
void PrincipalFn (char input [], void (* ptr) (char [50] ))
{
(* ptr) (ввод);
cout
}
void fn ()
{
cout
}
int main ()
{
char input [] = «функция обратного вызова»;
void (* ptr) (char []) = & cb;
PrincipalFn (input, cb);
fn ();
cout
return 0;
}
Результатом программы является:
замечено
функция обратного вызова
В этом конкретном коде выходные и входные данные совпадают. Результат третьего вызова функции в функции main () был отображен перед результатом функции обратного вызова. Функция обратного вызова выполнила, завершила и присвоила свой результат (значение) переменной output, что позволило программе продолжить работу без ее вмешательства. В функции main () выходные данные функции обратного вызова использовались (считывались и отображались), когда это было необходимо, что приводило к асинхронному поведению для всей схемы.
Это однопоточный способ для получения асинхронного поведения функции обратного вызова с чистым C ++.
Базовое использование будущей библиотеки
Идея схемы асинхронной функции обратного вызова заключается в том, что основная функция возвращается до функция обратного вызова возвращается. Это было сделано косвенно и эффективно в приведенном выше коде.
Обратите внимание на приведенный выше код, что функция обратного вызова получает основной ввод для кода и производит основной вывод для кода. В будущей библиотеке C ++ будет функция sync (). Первым аргументом этой функции является ссылка на функцию обратного вызова; второй аргумент — это вход для функции обратного вызова. Функция sync () возвращается, не дожидаясь завершения выполнения функции обратного вызова, но позволяет функции обратного вызова завершиться. Это обеспечивает асинхронное поведение. Пока функция обратного вызова продолжает выполняться, поскольку функция sync () уже вернулась, операторы под ней продолжают выполняться. Это похоже на идеальное асинхронное поведение.
Вышеупомянутая программа была переписана ниже с учетом будущей библиотеки и ее функции sync ():
#include
#include
с использованием пространства имен std;
будущий output;
string cb (string stri)
{
return stri;
}
void PrincipalFn (ввод строки)
{
output = async (cb, input);
cout
}
void fn ()
{
cout
}
int main ()
{
string input = string («функция обратного вызова»);
PrincipalFn (input);
fn ();
строка ret = output.get (); //ожидает возврата обратного вызова, если необходимо
cout
return 0;
}
Наконец, функция sync () сохраняет вывод функции обратного вызова в будущий объект. Ожидаемый результат может быть получен в функции main (), используя функцию-член get () будущего объекта.
Заключение
Функция обратного вызова — это функция , который является аргументом, а не параметром другой функции. Схема функции обратного вызова требует основной функции и самой функции обратного вызова. Объявление функции обратного вызова является частью списка параметров основной функции. Определение функции обратного вызова указывается в вызове функции основной функции (в main ()). Функция обратного вызова фактически вызывается в определении основной функции.
Схема функции обратного вызова не обязательно является асинхронной. Чтобы быть уверенным, что схема функции обратного вызова является асинхронной, сделайте основной ввод в код, ввод для функции обратного вызова; сделать основной вывод кода выводом функции обратного вызова; сохранить вывод функции обратного вызова в переменной или структуре данных. В функции main () после вызова основной функции выполните другие операторы приложения. Когда требуется вывод функции обратного вызова, в функции main () используйте (прочтите и отобразите) его тут же.