回调函数的工作机制(Callback)
回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。回调函数不是由函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行相应。
回调函数工作机制有两点,第一:使用函数指针,当我们希望在某个函数中使用另一个未知的函数时,可以将该未知函数的指针传递给这个函数。这种方式使得调用方无需了解被调用函数的具体实现细节;
第二,参数传递,在调用 Callback 函数时,我们可以传递参数给它,从而提供额外的上下文信息。这样,被调用的函数可以根据这些参数执行特定的操作,使得调用方与被调用方之间保持解耦。
Lab5.2中实现的回调函数是linktable.c文件中的SearchLinkTableNode()函数:
/*
* Search a LinkTableNode from LinkTable
* int Condition(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,
int Condition(tLinkTableNode * pNode, void * args),
void * args)
//condition函数作为参数传入,call-in方式函数结构
{
if(pLinkTable == NULL || Condition == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != NULL)
{
if(Condition(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
这里的函数传入参数有一个名为condition的回调函数,这个函数在执行过程中就会调用这个condition函数。传入的是一个condition函数指针,condition函数接受一个LinkTableNode类型的指针和一个void类型的指针作为参数。
menu.c
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{ //查询条件
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
menu.c文件中的SearchCondition函数作为具体的条件函数Condition传递给SearchLinkTableNode函数(在FindCmd中实现了回调函数的使用)
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
通过参数进行解耦合
在上述回调函数的实现过程中,menu.c中的FindCmd函数调用函数SearchLinkTableNode函数时,通过参数传入了函数SearchCondition的指针,在函数Search Link Table Node执行过程中,调用了SearchCondition函数。
SearchLinkTableNode函数并不在意SearchCondition的实现,只要SearchCondition的接口满足指定类型的输入输出。因此我们就可以在不改变函数接口的基础上随意修改传入的函数指针,就可以在不改变SearchLinkTableNode的同时实现不同的功能,实现了解耦合。