回調(diào)函數(shù)(C/C++)
1.相關(guān)解釋
①百度百科解釋:
回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這個(gè)指針(地址)所代表的函數(shù)為回調(diào)函數(shù)。
②維基百科解釋:
In computer programming, a callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time. This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback
也就是說,把一段可執(zhí)行代碼像參數(shù)傳遞那樣給其他代碼,而這段代碼會(huì)在某個(gè)時(shí)刻被調(diào)用執(zhí)行,這就叫做回調(diào)。如果代碼立即被執(zhí)行就稱為同步回調(diào),如果在之后晚點(diǎn)的某個(gè)時(shí)候再執(zhí)行,則稱之為異步回調(diào)
③Stack Overflow上一段解釋:
A "callback" is any function that is called by another function which takes the first function as a parameter
也就是說,函數(shù)F1調(diào)用函數(shù)F2的時(shí)候,函數(shù)F1通過參數(shù)給函數(shù)F2傳遞了另外一個(gè)函數(shù)F3的指針,在函數(shù)F2執(zhí)行的過程中,函數(shù)F2調(diào)用了函數(shù)F3,這個(gè)動(dòng)作就叫做回調(diào),而先被當(dāng)做指針傳入、后面又被回調(diào)的函數(shù)F3就是回調(diào)函數(shù)。
插入一張維基百科上的解釋圖片

2.為什么要使用回調(diào)函數(shù)
解耦
為什么不能像普通函數(shù)調(diào)用那樣,在回調(diào)的地方直接寫函數(shù)名字呢?其實(shí)很多回調(diào)函數(shù)的例子完全可以用普通函數(shù)調(diào)用來實(shí)現(xiàn)的。這里引入一個(gè)名詞解耦,就是因?yàn)榻怦?,普通函?shù)代替不了回調(diào)函數(shù)。
下面引入一個(gè)例子:
#include<stdio.h>
#include<softwareLib.h> // 包含Library Function所在讀得Software library庫的頭文件
int Callback() // Callback Function
{
// TODO
return 0;
}
int main() // Main program
{
// TODO
Library(Callback);
// TODO
return 0;
}
乍一看,回調(diào)似乎只是函數(shù)間的調(diào)用,和普通函數(shù)調(diào)用沒啥區(qū)別,但仔細(xì)一看,可以發(fā)現(xiàn)兩者之間的一個(gè)關(guān)鍵的不同:在回調(diào)中,主程序把回調(diào)函數(shù)像參數(shù)一樣傳入庫函數(shù)。這樣一來,只要我們改變傳進(jìn)庫函數(shù)的參數(shù),就可以實(shí)現(xiàn)不同的功能,這樣有沒有覺得很靈活?并且絲毫不需要修改庫函數(shù)的實(shí)現(xiàn),這就是解耦。
再仔細(xì)看看,主函數(shù)和回調(diào)函數(shù)是在同一層的,而庫函數(shù)在另外一層,想一想,如果庫函數(shù)對(duì)我們不可見,我們修改不了庫函數(shù)的實(shí)現(xiàn),也就是說不能通過修改庫函數(shù)讓庫函數(shù)調(diào)用普通函數(shù)那樣實(shí)現(xiàn),那我們就只能通過傳入不同的回調(diào)函數(shù)了,這也就是在日常工作中常見的情況。現(xiàn)在再把main()、Library()和Callback()函數(shù)套回前面 F1、F2和F3函數(shù)里面,是不是就更明白了?
3.調(diào)用帶參數(shù)的回調(diào)函數(shù)
話不多說直接上代碼:
#include<stdio.h>
int Callback_1(int x) // Callback Function 1
{
printf("Hello, this is Callback_1: x = %d ", x);
return 0;
}
int Callback_2(int x) // Callback Function 2
{
printf("Hello, this is Callback_2: x = %d ", x);
return 0;
}
int Callback_3(int x) // Callback Function 3
{
printf("Hello, this is Callback_3: x = %d ", x);
return 0;
}
int Handle(int y, int (*Callback)(int))
{
printf("Entering Handle Function. ");
Callback(y);
printf("Leaving Handle Function. ");
}
int main()
{
int a = 2;
int b = 4;
int c = 6;
printf("Entering Main Function. ");
Handle(a, Callback_1);
Handle(b, Callback_2);
Handle(c, Callback_3);
printf("Leaving Main Function. ");
return 0;
}
運(yùn)行結(jié)果:
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1: x = 2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2: x = 4
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3: x = 6
Leaving Handle Function.
Leaving Main Function.
可以看到,并不是直接把int Handle(int (Callback)()) 改成 int Handle(int (Callback)(int)) 就可以的,而是通過另外增加一個(gè)參數(shù)來保存回調(diào)函數(shù)的參數(shù)值,像這里 int Handle(int y, int (*Callback)(int)) 的參數(shù) y。同理,可以使用多個(gè)參數(shù)的回調(diào)函數(shù)。
原鏈接:https://www.runoob.com/w3cnote/c-callback-function.html
(稍有修改)