版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/qq_29924041/article/details/74857469 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
<div id="content_views" class="markdown_views">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p><strong>C++学习:回调函数(callback)</strong></p>
简介:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
可能这些概念性的东西不是太好理解,通俗一点,回调函数就是在两个独立函数或者独立类通信的通道
举个例子:
财务处是负责对公司财务状况和每个月的开销进行汇总
老板只会去看每个月的报表
那么在这个当中,老板不会去关心,财务整个汇总的过程,他只会去关心结果,那么,如果从面向对象的方法去理解的话,老板是一个对象.财务部是一个对象,当老板想看报表的时候,会跟财务打个招呼,等财务部汇总完了.然后将报表再去提交给老板,那么问题来了,而两个类之间实现通信的就是接口回调,从财务类的中,将结果回调到对象中.这种实现是通过接口自动完成的
如果用C语言的面向过程去理解的话,那么老板想看报表可以理解为一个函数,而财务处计算过程可以看成一个函数,如果老板想看报表的话,可以直接通过调用财务处函数的返回结果来查看.这中主要是依赖于函数指针的形式来实现
提示:
博客:章飞_906285288
博客地址:http://blog.youkuaiyun.com/qq_29924041
基于C语言的回调函数来实现一个回调的过程
/*
* ===========================================================================
*
* Filename: callback.c
* Description:
* Version: 1.0
* Created: 2017年07月09日 10时27分28秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include<stdlib.h>
/* *
*财务的统计状况函数
* */
static int finance_result(int *a,int n);
/* *
*老板想看财务报表
* */
void boss_read_finance(int *array,int n,int (*fp)(int*,int));
int main(int argc,char* argv[]){
//定义一个数组数据
int array[10] = {1,2,3,4,5,6,7,8,9,10};
//因为C语言中函数名也是地址,因此对于形参数是函数指针的话,这个时候直接将地址传进去就可以了;
//注意:函数指针是指向函数的地址,对于fp是地址,那么调用的时候固然需要(*fp)
//也可以这样写:
//int (*fp)(int *a,int n);
//fp = finance_result;
//boss_read_finance(array,10,finance_result);
boss_read_finance(array,10,finance_result);
return 0;
}
/* *
*老板查看财务状况的实现,参数中有一个函数指针,
* */
void boss_read_finance(int* array,int n,int (*fp)(int* a,int n)){
//对于老板来说,他是不需要去了解财务部的具体实现的过程,只要结果就行了
//这就有助于我们对函数封装
int result = (*fp)(array,n);
printf("caculate result:%d\n",result);
}
/* **
*财务计算报表的具体实现
* */
static int finance_result(int* a,int n){
int result = 0;
int i = 0;
for(i = 0;i < n; i++){
result += *(a+i);
}
return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
基于C++面向对象过程的代码
/*
* ===========================================================================
*
* Filename: finance.h
* Description:
* Version: 1.0
* Created: 2017年07月09日 10时52分53秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#ifndef __FINANCE_H__
#define __FINANCE_H__
namespace zzf{
#include<iostream>
using namespace::std;
/* *
*定义一个callback的接口
* */
class CallBack{
public:
virtual void setFinanceResult(int result) const = 0;
};
/* *
*财务:
专门用于计算结果的
* */
class Finance{
public:
Finance(CallBack* mCallBack2):mCallBack(mCallBack2){
cout << "finance constructor" << endl;
}
~Finance(){
cout << "finance destructor" << endl;
}
void caculateFinance(int * a,int n){
int result = 0;
for(int i = 0 ;i < n;i++){
result += *(a + i);
}
if(mCallBack != NULL){
cout <<"result:"<<result<<endl;
mCallBack->setFinanceResult(result);
}
}
private:
CallBack* mCallBack;
};
/* *
*老板,实现接口callback
* */
class Boss:public CallBack{
public:
Boss(){
//将接口实例化后,传递给Finance
mFinace = new Finance(this);
cout << "boss constructor" << endl;
}
~Boss(){
delete mFinace;
cout << "boss destructor" << endl;
}
//查看财务的函数
void readFianace(int *array ,int n){
cout << "boss readFianace"<< endl;
mFinace -> caculateFinance(array,n);
}
//实现后的回调函数,这个函数就是用来接收回调的值的
void setFinanceResult(int result) const{
cout << "caculate result:" << result << endl;
}
private:
Finance *mFinace;
};
}
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
/*
* ===========================================================================
*
* Filename: testFinance.cpp
* Description:
* Version: 1.0
* Created: 2017年07月09日 11时04分55秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<iostream>
#include<finance.h>
using namespace::std;
using namespace::zzf;
int main(int argc,char *argv []){
int array[10] = {1,2,3,4,5,6,7,8,9,10};
Boss boss;
boss.readFianace(array,10);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
其实这个案例能够让我们对回调有更加深刻的认识:
1:老板想查看财务(调用自己函数,函数在boss内)
2:通知财务,我要查看报表(进行计算的过程,函数在finance内部)
3:财务算好之后,返回给老板(回调的函数在boss内部)
也就是回调就是把不需要自己处理的东西放到别的类去,然后等其处理完毕之后,再返回给调用的类.
总结:
回调四步曲:
- 定义一个回调接口
- 调用类去实现这个接口,重写方法
- 被调用者将接口做为参数传递进去,并且在某个时刻进行出发
- 调用者在调用的时候去实例化这个回调接口(如上述案例中因为已经实现了接口,所以将类本身对应的对象作为参数传递进去)