C|理解回调函数回调机制原理(主调函数和被调函数互不依赖)

(31) 2023-10-12 08:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说C|理解回调函数回调机制原理(主调函数和被调函数互不依赖),希望能够帮助你!!!。

回调函数是利用函数指针做函数参数,实现的一种调用机制,具体任务的实现者,可以不知道什么时候被调用。

回调机制原理:

当具体事件发生时,调用者通过函数指针调用具体函数。

回调机制的将调用者和被调函数分开,两者互不依赖。

任务的实现和任务的调用可以实现松耦合(提前进行接口的封装和设计)。

看以下实例:

#include <iostream>
using namespace std;
int add(int a, int b);
void libfun(int (*pDis)(int a, int b));

int main(void)
{
   int (*pfun)(int a, int b);
   pfun = add;
   libfun(pfun);
   return 0;
}

int add(int a, int b)
{
   return a + b;
}
int minus(int a, int b)
{
   return a - b;
}
void libfun(int (*pDis)(int a, int b))
{
   int a, b;
   a = 1;
   b = 2;
   int c = add(a,b);  	//直接调用add函数
   c = pDis(a, b);
   printf("%d", c);  	//通过函数指针做函数参数,间接调用add函数
   //思考这样写pDis(a, b)有什么好处?
}

假设要实现减法呢?现在这几个函数是在同一个文件当中,可以直接在

int libfun(int (*pDis)(int a, int b))

中修改,假设libfunc()是一个库中的函数,你就只能使用函数指针的回调机制了,通过函数指针参数将外部函数地址传入来实现调用。

当然,函数 add()或minus() 的代码作了修改,也不必改动库的代码,就可以正常实现调用。

最重要的是,即使将add换成另一个函数,也不需要修改libfun(),只需在调用时将其函数指针参数使用不同的实参就行了。这就是低耦合的思想,便于程序的维护和升级。

再看一个例子:

#include <iostream>
using namespace std;

bool  lesser(int a, int b);
bool greater(int a, int b);
void libSwap(bool (*pDis)(int a, int b));   // 通过函数直接来调用lesser()或greater()函数
void libSwap();                           // 直接在函数体内调用lesser()或greater()函数

int main(void)
{
    libSwap(lesser);
    //libSwap(greater);
    libSwap();
    while(1);
    return 0;
}

bool greater(int a, int b)
{
    return a > b;
}
bool lesser(int a, int b)
{
    return a < b;
}

void libSwap(bool (*pDis)(int a, int b)) //通过函数指针做函数参数,间接调用add函数
{
    int a = 5, b = 7;
    if(pDis(a, b))                  
    {
        int tmp = a;
        a = b;
        b = tmp;
    }
    cout<<a<<" "<<b<<endl;
    
}
void libSwap()              //直接在函数体内调用lesser()或greater()函数
{
    int a = 5, b = 7;
    if(lesser(a,b))
    //if(greater(a,b))
    {
        int tmp = a;
        a = b;
        b = tmp;
    }
    cout<<a<<" "<<b<<endl;
}

上列假设libSwap()是库函数。库使用者在main()中调用

void libSwap(bool (*pDis)(int a, int b))

此函数有一个函数指针,需要提供函数供其使用,此时库使用者编写greater()、lesser(),这两个函数库使用者并不直接调用,而是由libSwap()去调用。greater()、lesser()这种函数就称为回调函数,整个设计机制就是回调函数调用机制。

所谓回调,就是客户程序C调用服务程序S中的某个函数s(),然后S又在某个时候反过来调用C中的某个函数c(),对于C来说,这个c()便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。

一般说来,C不会自己调用c(),c()提供c()的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的c()叫甚名谁,所以S会约定c()的接口规范(函数原型),然后由C提前通过S的一个函数r()告诉S自己将要使用c()函数,这个过程称为回调函数的注册,R称为注册函数。

在框架中,定义函数指针,相当于提前指定了一套协议接口。

对于排序函数,如果想用同一个排序函数来实现升序或降序排列,调用时不修改此函数的排序逻辑,可以考虑使用函数指针来调用回调函数,而stdlib.h库中的qsort()函数即是如此来实现这一逻辑的:

#include <stdio.h>
#include <stdlib.h>

int compare(int a, int b)  // 用于bubbleSort()的回调函数
{
    return a-b;
    //return b-a;
}

int cmp(const void* a, const void* b) // 用于库函数qsort()
{
    return (*((int*)a) - *((int*)b));
    //return (*((int*)b) - *((int*)a));
}

void bubbleSort(int arr[], int n, int (*compare)(int,int)) 
{ // 只需更改函数指针指向的回调函数,即可实现升序或降序排列
    for(int i=0; i<n; i++)
        for(int j=0;j<n-i-1; j++)
            if(compare(arr[j],arr[j+1])>0)
            {
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
}

void arrOutput(int arr[], int n)
{
    for(int i=0;i<n; i++)
        printf("%d ",arr[i]);
    printf("\n");
}

int main()
{
    int arr[] = {3,2,1,5,4};
    int n = sizeof(arr)/sizeof(arr[0]);
    bubbleSort(arr,n,compare);
    arrOutput(arr,n);

    int arr2[] = {3,2,1,5,4};
    qsort(arr2,n,sizeof(int),cmp);
    arrOutput(arr2,n);
    while(1);
    return 0;
}
/*
1 2 3 4 5
1 2 3 4 5
*/
C|理解回调函数回调机制原理(主调函数和被调函数互不依赖)_https://bianchenghao6.com/blog__第1张

-End-

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复