回调函数主要用于统一不同调用函数接口,针对不同调用函数:void ShowImage();void ShowWindow()。。。
将它们封装起来同一函数接口,void imput(void (*callback)())
void imput(void (*callback)())
{
(*callback)();
}
或者
void imput(int n ,void (*callback)())
{
(*callback)(n);
}
将回调函数地址传给调用函数实现调用
为什么要使用回调函数呢?小例子:
Node * Search_List (Node * node, const int value)
{
\*对于 Node * Search_List (Node * node, void *value)由于不确定指针类型并不能进行比较,所以需要引入毁掉函数来封装不同类型的比较 *\
while (node != NULL)
{
if (node -> value == value)
{
break;
}
node = node -> next;
}
return node;
}
由于指定了比较类型,所以这个函数值能比较int型。显然不利于封装(如果对于一个字符串链表比较,显然不能)
我们引入回调函数,回调函数包含指定的比较类型,int_cmp(), float_cmp(), double_cmp(),我们用
在申明时,
NODE *Search_List(NODE *node, int (*compare)(void const *, void const *) , void const *desired_value)
{
while (node != NULL)
{
if (compare((node->value_address), desired_value) == 0)\* 调用compare知识传入参数并未指定类型,调用时自行确定类型,这样具有通用性 *\
{
break;
}
node = node->next;
}
return node;
}
可以看到,用户将一个函数指针传递给查找函数,后者将回调这个函数,上面并没有制定比较函数的具体定义,只是形式定义,具体调用时我们可以运用
Search_List(NODE , int _compare(void *, void *) , void*desired_value);
Search_List(NODE , float_compare(void *, void *) , void*desired_value) ;
而在使用时,需要针对不同比较类型进行强制转换指针类型后才能使用。int指针占四个字节,double6字节吗,才能正常*取指针值。
int int_compare(void const *a, void const *b)
{
if (*(int *)a == *(int *)b)
{
return 0;
}
else
{
return -1;
}
}
链表节点是这样定义的:
typedef struct list
{
void *value_address;
struct list *next;
}NODE;
这样定义可以让NODE *类型的指针指向存储任何类型数据的链表节点。而value_address就是指向具体数据的指针,我们把它定义为void *,表示一个指向未知类型的指针,这样链表就可以存储任何类型的数据了,而我们传递给查找函数Search_List的第一个参数就可以统一表示为:NODE *,否则,还是要分别写查找函数以适应存储不同数据类型的链表。
现在,查找函数与类型无关,因为它不进行实际的比较,因此,我们必须编写针对不同类型的比较函数,这是很容易实现的,因为调用者知道链表中所包含的值的类型,如果创建几个分别包含不同类型值的链表,为每种类型编写一个比较函数就允许单个查找函数作用于所有类型的链表。
当我们想通过一个统一接口实现不同内容的时候,用回调函数来实现就非常合适。任何时候,如果你所编写的函数必须能够在不同的时刻执行不同的类型的工作或者执行只能由函数调用者定义的工作,你都可以用回调函数来实现。许多窗口系统就是使用回调函数连接多个动作,如拖拽鼠标和点击按钮来指定调用用户程序中的某个特定函数。
#include<iostream>
using namespace std;
int search(void *, int (*cmp)(void*, void*), void *);
int cmp1(void *a, void *b);
int main()
{
int a = 34, b = 3,c=6;
int * pa=&a, * pb=&b;
c=search(pa,cmp1,pb);
return c;
}
int search(void *a, int(*cmp)(void*, void*), void *b)
{
if (cmp(a, b))
{
return 5;
}
else
{
return 2;
}
}
int cmp1(void *a, void *b)
{
if (*(int *)a==*(int*)b)
{
return 1;
}
else
{
return 0;
}
}
a!=b,return2;
a==b,return5;