一、回调函数机制
/*
* 1.回调函数机制的出现:最初,编程时需要调用某个库函数,但是被调用的库函数的某个输入参数是一个函数指针,即指向其他函数的指针,这个其他函数通函数中一般没有,而是需要编程者自己编写。这样本来编程者要调用库函数,而库函数又要返回过来调用编程者自己的一个函数,这就构成了回调函数机制。
* 2.著名的回调函数机制的实现:是C/C++标准库stdlib.h/cstdlib中的快速排序函数qsort和二分查找函数bsearch中,两者都需要一个比较函数作为输入参数,来比较两个变量的大小来辅助实现排序与查找。
* void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
* void *bsearch(const void *key, const void *base, size_t nelem, size_t width, int(*fcmp)(const void *, const void *));
* 3.回调函数机制的本质:回调函数机制的本质是,某个函数(以下称本体函数)的某个输入参数是个函数指针,因而可以将其他函数(即回调函数)的功能作为本体函数的一部分。
* 4.回调函数的设计目的:本体函数的运行功能中有一部分是可替换的,即通过回调函数实现。这样,可让本体函数的核心功能有多种实现方式,从而实现了本体函数的多态化运行,以适应不同的需求情况。
*/
#include <stdio.h>
/*******************************************************
* 本体函数:calculate().
******************************************************/
int calculate( int(* callback_func)(int,int), int a, int b )
{
int tmp0;
tmp0=callback_func(a,b);
int tmp1;
tmp1=tmp0+10000;
return tmp1;
}
/**************************************************
* 四个回调函数:add(), sub(), multiply(), divide().
*************************************************/
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int multiply(int a, int b)
{
return a*b;
}
int divide(int a, int b)
{
return a/b;
}
/********************************************
* 主函数main()
********************************************/
int main()
{
int result;
result=calculate(add, 10, 5);
printf("The result is :%d.\n\n", result);
result=calculate(sub, 10, 5);
printf("The result is :%d.\n\n", result);
result=calculate(multiply, 10, 5);
printf("The result is :%d.\n\n", result);
result=calculate(divide, 10, 5);
printf("The result is :%d.\n\n", result);
return 0;
}
二、注册函数机制
/*
* 1.注册函数机制的出现:现在(公元2024年)的大型程序开发,一般都是由一些公司开发出通用的框架程序,而后其他开发者(开发公司)在这些框架程序上进行二次开发。在设计程序框架时,通用框架功能之外的具体功能是要留给框架程序应用者去二次开发实现的,但是这种二次开发要在框架程序的控制范围之内,实现的方法就是留下具体功能的函数指针型变量接口,而不具体实现功能函数,另外提供一种注册函数给二次开发者,来将新开发的函数注册(赋值)给框架程序预留的函数指针型变量接口。
* 2.著名的注册函数机制的实现:微软的MFC程序开发中的消息处理函数,如按键消息处理函数OnKeyDown(),鼠标消息处理函数OnLButtonDown()、OnRButtonUp()和OnMouseMove()等都是要求二次开发重写的。
* 3.注册函数机制的本质:注册函数机制的本质是,前面的开发中预先留下一个函数指针型全局变量,作为后期开发的接口函数(或称函数接口、本体函数接口)。后期开发出具体的功能函数后,通过前期开发提供的注册函数将后期开发的函数名(即函数指针)赋值给前期开发预留的函数指针型全局变量,即实现了前期开发预留的接口函数。
* 4.注册函数的设计目的:为二次开发者预留函数接口,由二次开发者具体实现特定的二次开发功能。
*/
#include <stdio.h>
/***********************************************
* 本体函数接口(接口函数、函数接口)类型定义。
***********************************************/
typedef int(* calculate_func)(int, int);
/************************************************
* 本体函数接口(接口函数、函数接口),即全局变量定义。
************************************************/
calculate_func calculate;
/*******************************************************
* 注册函数:register_func().
******************************************************/
int register_func(calculate_func func)
{
calculate=func;
return 0;
}
/**************************************************
* 四个被注册函数:add(), sub(), multiply(), divide().
*************************************************/
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int multiply(int a, int b)
{
return a*b;
}
int divide(int a, int b)
{
return a/b;
}
/********************************************
* 主函数main()
********************************************/
int main()
{
int result;
register_func(add);
result=calculate(10, 5);
printf("The result is :%d.\n\n", result);
register_func(sub);
result=calculate(10, 5);
printf("The result is :%d.\n\n", result);
register_func(multiply);
result=calculate(10, 5);
printf("The result is :%d.\n\n", result);
register_func(divide);
result=calculate(10, 5);
printf("The result is :%d.\n\n", result);
return 0;
}
三、 回调函数机制与注册函数机制的区别:
* (1)很多文章混淆了回调函数机制与注册函数机制,两者是两种不同的待定函数设计机制/设计思想。
* (2)回调函数机制的设计目的是为了实现本体函数中部分功能的可替换。回调函数机制中的本体函数已经实现了一部分功能。
* (3)注册函数机制的设计目的是为了实现本体函数的完全替换。事实上注册函数机制的本体函数完全未实现,是函数定义(声明)与函数实现的彻底分离。
* (4)回调函数机制的实现比较简单。包括:
* A.设计本体函数(一个参数为回调函数型函数指针,其他参数与回调函数的输入参数相同)。
* B.设计回调函数(一般有多个)。
* C.调用本体函数(参数为回调函数,及回调函数的输入参数)。
* (5)注册函数机制的实现要复杂一些。包括:
* A.定义本体函数类型
* B.声明本体函数型全局变量,即声明(定义)本体函数。
* C.设计注册函数,
* D.设计被注册函数(一般有多个)。
* E.注册:即调用注册函数将某个被注册函数名(即函数指针)赋值给本体函数型全局变量。
* F.调用本体函数(通过上面的本体函数型全局变量实现调用)。
四、回调函数机制与注册函数机制的相似之处:(注意,只是相似,不是说二者有联系。正因为相似,所以导致两种机制的混淆)
* (1)回调函数与被注册函数的形式都是预先固定好的,都要求后续开发者必须事先了解、并严格遵守预定的函数接口形式。
* (2)都实现了本体函数的多态化。