1.回调函数是什么?
回调函数是指通过函数参数传递到其它代码的某一块可执行代码的引用。百度百科对回调函数的定义是如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
2.Lab5.2 代码分析
概要分析:
在这个例子中,SearchLinkTableNode函数中使用Condition函数作为一个参数,SearchLinkTableNode在执行过程中会调用这个函数。在主函数menu.c中,FindCmd函数调用了SearchLinkTableNode函数进行搜索,它将搜索条件传递给SearchLinkTableNode函数,从而实现了解耦。
详细分析:
Callback 函数主要体现在 linktable.c 文件中的 SearchLinkTableNode() 函数中:
/*
* Search a LinkTableNode from LinkTable
* int Conditon(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
这里的Condition函数是一个函数指针(地址),它使用一个LinkTableNode类型的指针和一个void类型的指针作为参数。
在menu.c文件中,我们可以看到在FindCmd函数中使用到了这个回调函数,它将另一个函数SearchCondition作为参数传递给SearchLinkTableNode函数:
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
/* find a cmd in the linklist and return the datanode pointer */
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
这里的函数指针是:
int Conditon(tLinkTableNode * pNode, void * args)
它作为SearchLinkTableNode函数的一个参数。
在这个例子中,SearchLinkTableNode 函数使用一个 void 类型的指针作为参数。
/*
* Search a LinkTableNode from LinkTable
* int Conditon(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
menu.c 中的 FindCmd 函数调用 SearchLinkTableNode 函数,并使用一个指向字符串的指针作为参数:
/* find a cmd in the linklist and return the datanode pointer */
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
在 SearchLinkTableNode 函数内部,我们调用 Condition 时,同时传递这个 void 类型的指针:
/*
* Search a LinkTableNode from LinkTable
* int Condition(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,
int Condition(tLinkTableNode * pNode, void * args),
void * args)
{
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;
}
这样,我们可以在 SearchCondition 函数内部,根据传递的参数执行特定的操作:
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
回调函数实现了调用方与被调用方之间的解耦。在这个例子中,linktable 模块可以在不知道 menu 模块的具体实现细节的情况下,为其提供通用的链表操作。相应地,menu 模块可以根据自己的需求,利用这些通用操作实现特定的功能。
学号后三位:229