回调函数工作机制
简单来说,回调函数的工作机制如下:
- 当一个函数(称为Call-in函数)需要执行一个任务,但是这个任务的具体实现方式由另一个函数(称为Call-back函数)来决定时,Call-in函数就可以将Call-back函数作为参数传递给它。
- call-in函数在执行任务的过程中,会在合适的时机,通过函数指针、函数对象或匿名函数等方式,来调用call-back函数,并将一些必要的参数传递给它。
- call-back函数在接收到call-in函数的调用后,会根据传入的参数和自身的逻辑,来执行相应的操作,并返回结果给call-in函数。
- call-in函数在接收到call-back函数的返回结果后,会继续执行自己的任务,并根据需要再次调用call-back函数或其他函数。
在lab5.2的源代码中,给Linktable增加Callback方式的查询接口,需要两个函数接口,一个是call-in方式函数,如SearchLinkTableNode函数,其中有一个函数作为参数,这个作为参数的函数就是callback函数,如代码中Conditon函数。同时我们在程序设计中追求松散耦合,如果使用全局变量cmd会有非常大的风险,且不符合松散耦合的理念,因此我们将为call-bakc函数(即condition函数)和call-in函数(即SearchLinkTableNode函数)添加参数args,这样做可以将公共耦合转变为标记耦合,隐藏软件模块内部的实现细节。
/*
* Serach a LinkTableNode from LinkTable
* int Condition(tLinkTableNode *pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Condition(tLinkTableNode *pNode, void *args), void * args);
该接口的实现代码如下
/*
* Serach 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;
}
在这个实现代码中,我们并不知晓Condition函数的实现,而这个Condition函数是我们在menu.c中试图调用SearchLinkTableNode传入的函数指针,Condition的函数在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;
}
/* find a cmd in the linklist and return the datanode pointer */
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
总结来说,即是在调用call-in函数的模块中撰写call-back函数的实现,并将call-back函数指针传入call-in函数,实现回调。
学号:158