@Resource、@Autowired等几个注解的区别

Harmony OS 设备开发学习记录(七)-- 通过光敏电阻感知环境光

  返回  

C语言 —— 回调函数

2021/7/20 19:00:24 浏览:

文章目录

    • 函数指针
    • 回调函数
    • 回调函数作用
      • 1. 实现多态(解耦)
      • 2. 延迟调用

函数指针

https://www.cnblogs.com/zhengjiafa/p/5796283.html
作用:因为c语言中只有struct而struct不像c++中的class,他是没有成员函数的,所以使用函数指针,可以将函数作为成员函数
函数指针有两个用途:调用函数、做函数的参数(主要用途)
函数指针实例:

#include <stdio.h>

int Func(int x);   /*声明一个函数*/
int (*p) (int x);  /*定义一个函数指针*/
//函数定义
int Func(int x) {
    printf("asdf");
    return 1;
}

char (*PTRFUN1)(int);//定义一个函数指针
char glFun(int a)
{ 
    printf("out ");
    return 'd';
}
int main()
{
    p = Func;          /*将Func函数的首地址赋给指针变量p*/
    (*p)(2); //调用函数方式一
    PTRFUN1 = glFun; //将glFun函数首地址给指针变量
    PTRFUN1(2); //调用函数方式二

}

该实例并没有体现出函数指针的好处,反而使用起来更复杂。
但是通过下面的回调函数,我们就能看到函数指针的真正威力了,将函数作为参数传入另一个函数

回调函数

特性:使用函数的指针最重要的作用就是作为函数的参数。这在回调函数中完美体现。
正常情况下我们无法将一个函数传入另一个函数中。但是使用函数指针,我们可以将一个函数传入另一个函数中,这个特性在回调函数中使用,体现的淋漓尽致**。

#include<stdio.h>

//文件B.c
//形参使用函数指针,传入的是函数的首地址,这样我们就可以实现将函数传入另一个函数中了
//这里形参是一个函数指针,他可以接收其他函数传入。
//回调类型和库函数名称类似
void Handle(int y, int (*HandleCallbackT)(int)) 
{
    printf("Entering Handle Function. ");
    printf("\r\n");
    HandleCallbackT(y); //调用回调函数
    //Callback; //调用回调函数
    printf("Leaving Handle Function. ");
    printf("\r\n");
}

//文件A.c
int Callback_1(int x) // Callback Function 1
{
    printf("Hello, this is Callback_1: x = %d ", x);
    printf("\r\n");
    return 0;
}

int Callback_2(int x) // Callback Function 2
{
    printf("Hello, this is Callback_2: x = %d ", x);
    printf("\r\n");
    return 0;
}

int Callback_3(int x) // Callback Function 3
{
    printf("Hello, this is Callback_3: x = %d ", x);
    printf("\r\n");
    return 0;
}

//文件A.c
//callBack调用函数,调用函数和回调函数名称类似,因为他们是同一个文件,同一级
void CallBack() {
    int a = 2;
    int b = 4;
    int c = 6;

    //调用库函数,将回调函数传入,会在库函数中走回调函数
    //在哪里调用这个库函数,就在哪里写回调函数定义。
    Handle(a, Callback_1);//将callback1传入
    Handle(b, Callback_2);
    Handle(c, Callback_3);
}

//test测试
int main()
{
    printf("Entering Main Function. ");
    printf("\r\n");
    CallBack();
    //这里体现出优势,为何使用回调,其实就是为了解耦,我们可以将不同的回调函数传入handle
    //并且不需要改变handle函数,而我们可以传入不同的函数参数
    printf("Leaving Main Function. ");
    printf("\r\n");
    return 0;
}
/*
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1: x = 2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2: x = 4
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3: x = 6
Leaving Handle Function.
Leaving Main Function.
*/

回调函数作用

https://www.runoob.com/w3cnote/c-callback-function.html

1. 实现多态(解耦)

由于c语言没有面向对象的概念,所以使用回调来实现多态。也就是多态的作用其实就是解耦。
解耦,很多朋友可能会想,为什么不像普通函数调用那样,在回调的地方直接写函数的名字呢?这样不也可以吗?为什么非得用回调函数呢?
有这个想法很好,因为在网上看到解析回调函数的很多例子,其实完全可以用普通函数调用来实现的。要回答这个问题,我们先来了解一下回到函数的好处和作用,那就是解耦,对,就是这么简单的答案,就是因为这个特点,普通函数代替不了回调函数。所以,在我眼里,这才是回调函数最大的特点。来看看维基百科上面我觉得画得很好的一张图片。
在这里插入图片描述

#include<stdio.h>
#include<softwareLib.h> // 包含Library Function所在读得Software library库的头文件

int Callback() // Callback Function
{
    // TODO
    return 0;
}
int main() // Main program
{
    // TODO
    Library(Callback);
    // TODO
    return 0;
}

乍一看,回调似乎只是函数间的调用,和普通函数调用没啥区别,但仔细一看,可以发现两者之间的一个关键的不同:在回调中,主程序把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,这样有没有觉得很灵活?并且丝毫不需要修改库函数的实现,这就是解耦。再仔细看看,主函数和回调函数是在同一层的,而库函数在另外一层,想一想,如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了,这也就是在日常工作中常见的情况。现在再把main()、Library()和Callback()函数套回前面 F1、F2和F3函数里面,是不是就更明白了?

明白了回调函数的特点,是不是也可以大概知道它应该在什么情况下使用了?没错,你可以在很多地方使用回调函数来代替普通的函数调用,但是在我看来,如果需要降低耦合度的时候,更应该使用回调函数。

2. 延迟调用

项目中使用的都是都是异步,我觉得最大的用处就是异步,延迟回调。当一个操作非常耗时,而且可能出现崩溃的情况下,使用异步回调函数。主函数调用这个耗时函数之后会继续往下走,而不会被阻塞住。这个耗时函数就自己去执行,等执行完成之后会调用回调函数,这样不影响主函数的其他操作。异步的功能是底层提供给上层的, 我们自己写的回调函数,比如上面的例子中,都是同步回调。

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号