一、回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 
回调函数机制: 
1、定义一个函数(普通函数即可); 
2、将此函数的地址注册给调用者; 
3、特定的事件或条件发生时,调用者使用函数指针调用回调函数。 
注:为什么要特定事件或条件发生?不应该随时都可以调用回调函数吗? 
以下是回调函数的两种使用方式(简单理解): 
1、

#include <stdio.h>
typedef int(*callback)(int,int); int add(int a,int b,callback p){
return (*p)(a,b);
} int add(int a,int b){
return a+b;
}
int main(int argc,char *args[]){
int res = add(4,2,add);
printf("%d\n",res);
return 0;
}

在这个例子中,可以看到,我们定义了一个callbak的函数指针,参数为两个int,返回值为int,通过调用函数地址来进行简单的相加运算。 
2、

#include <stdio.h>
typedef int (callBack)(const void *buffer,size_t size,char *p_out); void callFunc(callBack *consume_bytes, char *p_out) {
printf("callFunc\n");
const void *buffer = NULL;
consume_bytes(buffer,0,p_out); //传入值可以随便填
} int callBackFunc(const void *buffer, size_t size, char *p_out){
printf("callBackFunc\n");
memset(p_out,0x00,sizeof(char)*100);
strcpy(p_out,"encoderCallback:this is string.");
return 1;
} int main(int argc,char *args[]){
char p_out[100];
callFunc(callBackFunc,p_out);
printf("%s\n",p_out);
return 0;
}

可以把回调函数和调用函数封装承类再调用。

二、在理解“回调函数”之前,首先讨论下函数指针的概念。

函数指针

(1)概念:指针是一个变量,是用来指向内存地址的。一个程序运行时,所有和运行相关的物件都是需要加载到内存中,这就决定了程序运行时的任何物件都可以用指针来指向它。函数是存放在内存代码区域内的,它们同样有地址,因此同样可以用指针来存取函数,把这种指向函数入口地址的指针称为函数指针。

(2)先来看一个Hello World程序:

int main(int argc,char* argv[])
{
printf("Hello World!\n");
return 0;
}

然后,采用函数调用的形式来实现:

void Invoke(char* s);

int main(int argc,char* argv[])
{
Invoke("Hello World!\n");
return 0;
}

void Invoke(char* s)
{
printf(s);
}

用函数指针的方式来实现:

void Invoke(char* s);

int main()
{
void (*fp)(char* s); //声明一个函数指针(fp)
fp=Invoke; //将Invoke函数的入口地址赋值给fp
fp("Hello World!\n"); //函数指针fp实现函数调用
return 0;
}

void Invoke(char* s)
{
printf(s);
}

由上知道:函数指针函数的声明之间唯一区别就是,用指针名(*fp)代替了函数名Invoke,这样这声明了一个函数指针,然后进行赋值fp=Invoke就可以进行函数指针的调用了。声明函数指针时,只要函数返回值类型、参数个数、参数类型等保持一致,就可以声明一个函数指针了。注意,函数指针必须用括号括起来 void (*fp)(char* s)。

实际中,为了方便,通常用宏定义的方式来声明函数指针,实现程序如下:

typedef void (*FP)(char* s);
void Invoke(char* s);

int main(int argc,char* argv[])
{
FP fp; //通常是用宏FP来声明一个函数指针fp
fp=Invoke;
fp("Hello World!\n");
return 0;
}

void Invoke(char* s)
{
printf(s);
}

函数指针数组

下面用程序对函数指针数组来个大致了解:

#include <iostream>
#include <string>
using namespace std;

typedef void (*FP)(char* s);
void f1(char* s){cout<<s;}
void f2(char* s){cout<<s;}
void f3(char* s){cout<<s;}

int main(int argc,char* argv[])
{
void* a[]={f1,f2,f3}; //定义了指针数组,这里a是一个普通指针
a[0]("Hello World!\n"); //编译错误,指针数组不能用下标的方式来调用函数

FP f[]={f1,f2,f3}; //定义一个函数指针的数组,这里的f是一个函数指针
f[0]("Hello World!\n"); //正确,函数指针的数组进行下标操作可以进行函数的间接调用

return 0;
}

回调函数

(1)概念:回调函数,顾名思义,就是使用者自己定义一个函数,使用者自己实现这个函数的程序内容,然后把这个函数作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。

(2)标准Hello World程序:

int main(int argc,char* argv[])
{
printf("Hello World!\n");
return 0;
}

将它修改成函数回调样式:

//定义回调函数
void PrintfText()
{
printf("Hello World!\n");
}

//定义实现回调函数的"调用函数"
void CallPrintfText(void (*callfuct)())
{
callfuct();
}

//在main函数中实现函数回调
int main(int argc,char* argv[])
{
CallPrintfText(PrintfText);
return 0;
}

修改成带参的回调样式:

//定义带参回调函数
void PrintfText(char* s)
{
printf(s);
}

//定义实现带参回调函数的"调用函数"
void CallPrintfText(void (*callfuct)(char*),char* s)
{
callfuct(s);
}

//在main函数中实现带参的函数回调
int main(int argc,char* argv[])
{
CallPrintfText(PrintfText,"Hello World!\n");
return 0;
}
 

至此,对回调函数应该有了一个大致的了解。

                              改变自己,从现在做起-----------久馆

                                                                          

C++回调函数的理解与使用的更多相关文章

  1. 回调函数透彻理解Java

    http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...

  2. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  3. js回调函数(callback)理解

    Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...

  4. JavaScript callback function 回调函数的理解

    来源于:http://mao.li/javascript/javascript-callback-function/ 看到segmentfault上的这个问题 JavaScript 回调函数怎么理解, ...

  5. js回调函数的理解

    js回调函数(callback)理解 Mark! 讲之前说一句 function say(){ alert(,,,,,,,,) } var say=function (){ alert(,,,,,,, ...

  6. 关于js的callback回调函数的理解

    回调函数的处理逻辑理解:所谓的回调函数处理逻辑,其实就是先将回调函数的代码 冻结(或者理解为闲置),接着将这个回调函数的代码放到回调函数管理器的队列里面. 待回调函数被触发调用的时候,对应的回调函数的 ...

  7. JavaScript回调函数的理解

    这里是个人对回调函数的一段理解 <!DOCTYPE html> <html> <head> <title>回调函数</title> < ...

  8. 通过回调函数的理解来进一步理解ajax及其注意的用法

    一,再一次理解回调函数 (function($){ $.fn.shadow = function(opts){ //定义的默认的参数 var defaults = { copies: 5, opaci ...

  9. js中的回调函数的理解

    一,常见的但是不是特别注意的回调方法. 1.1,ajax $.ajax({ url:"test.json", type: "GET", data: {usern ...

  10. java中回调函数的理解

    一,案例一 "通常大家说的回调函数一般就是按照别人(李四)的定好的接口规范写,等待别人(张三)调用的函数,在C语言中,回调函数通常通过函数指针来传递:在Java中,通常就是编写另外一个类或类 ...

随机推荐

  1. kali 系列学习08-安卓逆向

    可以轻松把安卓apk的源码逆向出来,逆向有什么用,比如手机apk木马,可以用于追踪黑客,详见  https://cloud.tencent.com/developer/news/179336 用2个工 ...

  2. 微信小程序生成二维码并且扫码跳转并且携带参数

    话不多说,直接上代码,直接把APPID和APPSECRET改成自己的就能用了 <?php header('content-type:text/html;charset=utf-8'); //配置 ...

  3. First day,beginning!

    beginning 在闲暇的时光记录当下的生活,一直是自己所期盼的: 由于种种原因(懒惰),一直未能开始,那么就从今天开始吧! 看下日期,从实习到现在一个月刚刚好: 公司很不错,师傅特别好,感觉自己是 ...

  4. python基础之条件语句

    检查相等和不等 多个检查条件 age1 = 22 age2 = 19 s1 = age1 > 21 and age2 > 19 print(s1) s2 = age1 > 21 or ...

  5. 基于gin的golang web开发:docker

    Golang天生适合运行在docker容器中,这得益于:Golang的静态编译,当在编译的时候关闭cgo的时候,可以完全不依赖系统环境. 一些基础 测试容器时我们经常需要进入容器查看运行情况,以下命令 ...

  6. Dapr DotNet5 HTTP 调用

    Dapr DotNet5 HTTP 调用 版本介绍 Dotnet 版本:5.0.100 Dapr dotnet 版本:0.12.0-preview01 注意: Asp.Net Core 项目中的 la ...

  7. 基于openeuler aarch_64 下,从源码的角度搭建Tensorflow

    为什么从源码编译Tensorflow? 安装过的人们都知道如果 pip install tensorflow 的话会报错Your CPU supports instructions that this ...

  8. Qt5字符串编码转换学习

    目录 1.通过Python3示例探索常用字符串编码 UTF8 ANSI Unicode 小结 2.Qt5中使用QTextCodec进行编码转换 小结 1.通过Python3示例探索常用字符串编码 下面 ...

  9. go语言的指针类型

    一.指针与引用的相关概念 什么是指针? 指针,全称为指针变量,是用来存储内存地址的一种变量.程序中,一般通过指针来访问其指向的内存地址中的内容(数据). 什么是引用? 引用,是C++中提出来的一种新的 ...

  10. PyQt(Python+Qt)学习随笔:model/view架构中的QStandardItemModel使用案例

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 1.案例说明 在应用中展示指定目录的图标文件的文件名和图标,界面就是一个简单的窗口上面放置一名为li ...