函数指针与回调机制
来源:互联网 发布:网店美工教学大纲 编辑:程序博客网 时间:2024/06/06 07:35
1.函数指针
普通指针:修改内存的值;函数指针:调用函数
一个简单的实例:
#include<stdio.h>void print(int n){ printf("result:%d\n",n*n);}int main(){ void (* p)(int); p=&print;//p=print;函数名就是指针地址 p(5); getchar(); return 0;}
函数指针的使用:
#include<stdio.h>void print(int n){ printf("result:%d\n",n*n);}typedef void (*my_Function)(int);//利用typedef为函数定义别名;防止可读性较差int main(){ my_Function p1=print; p1(5); getchar(); return 0;}
函数指针可以作为函数参数;
void test(my_Function p){ p(123);}
注:利用typedef可以增强函数的可读性;把函数指针变量同普通变量一样使用。
2.函数指针的回调机制
函数指针的应用场景:回调机制;
调用:调用第三方的类库(call)
回调:如果别人调用我们的函数叫回调(callback)
例子:拷贝文件
#include<stdio.h>#include <windows.h>//调用windows.api中的函数int main(){ const char *source="C:\\hao123.mp3"; const char *dst="D:\\hehe.mp3"; printf("start copy.......!\n"); bool result=CopyFile(source,dst,FALSE); //从源文件中拷到目标文件中去。 printf("operation done:%s\n",result ? "success" : "failed"); return 0;}
缺点:文件较大时,缺少交互性。
增强交互性:及时通知应用程序
希望系统在工作时,时不时地调用我们的函数函数。
使用windows api的copyFileEx()函数;
我们将函数地址传给系统api函数;
具体实现:
#include <stdio.h>#include <Windows.h>// 将LARGE_INTTEGER类型转成unsigned long longunsigned long long translate(LARGE_INTEGER num){ unsigned long long result = num.HighPart; result <<= 32; result += num.LowPart; return result;}// 回调函数// 注:要求将此函数用关键字CALLBACK修饰(这是Windows API的要求)DWORD CALLBACK CopyProgress( LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData){ // 文件的总字节数 TotalFileSize unsigned long long total = translate(TotalFileSize); // 已经完成的字节数 unsigned long long copied = translate(TotalBytesTransferred); // 打印进度 printf("进度: %I64d / %I64d \n", copied, total); // 64位整数用 %I64d //printf("进度: %d / %d \n", (int)copied, (int)total); // 文件大小于2G时,可以转成int return PROGRESS_CONTINUE;}int main(){ const char* source = "c:\\test\\2.rmvb"; const char* dst = "c:\\test\\2_copy.rmvb"; printf("start copy ...\n"); // 将函数指针传给CopyFileEx BOOL result = CopyFileEx(source, dst, &CopyProgress, NULL, NULL, 0); printf("operation done : %s \n", result ? "success" : "failed"); return 0;}
CopyProgress函数很好的体现了回调机制。
//
3.回调机制的补充
(1)回调函数的上下文
回调函数中总有一个参数传递上下文信息。
如:BOOL WINAPI CopyFileEx(…….,lppRoGress_Routine lpProgressRoutine,LPVOID lpData,…)
lp对象是指针类型;
上下文实现的是透传机制,API不关心上文对象的类型(void *),
定义上下文对象:
Struct Context{ char username[32]; char source[128]; char dst[128];};主函数中:Context ctx;strcpy(ctx.username,"张三");strcpy(ctx.source,"C:\\kt.mp3");strcpy(cx.dst,"D:\\jia.mp3");BOOL result = CopyFileEx(ctx.source,ctx.dst,&CopyProgress, &ctx,NULL, 0);回调的函数的上下文:Context* ctx = (Context*) lpData;
注:(1)上下文对象实现“透传”(void *);
(2)注意:上下文生命周期(对象函数必须是有效的);
(2)C++里的回调实现
.h文件中:
#ifndef _APCOPY_H#define _APCOPY_Hclass AfCopyFileListener{public: virtual int OnCopyProgress(long long total, long long transfered) = 0;};class AfCopyFile{public: int DoCopy(const char* source, const char* dst, AfCopyFileListener* listener);};#endif
要想实现DoCopy,则需要实现AfCopyFileListener接口;
一般接口类写成内部类;
接口实现:
class MainJob : public AfCopyFileListener{public: int OnCopyProgress(long long total, long long transfered) { // 打印进度 int percent = (int) ( (transfered * 100 / total) ); printf("[用户: %s], %s -> %s : 进度 %d %%\n", user, source, dst, percent); return 0; }public: char source[256]; char dst[256]; char user[64];};
缺点:回调的缺点是使逻辑比较混乱。
尽量避免使用回调。
0 0
- 函数指针与回调机制
- 函数指针和指针函数,函数指针与回调
- 函数指针与回调
- 函数指针与回调
- 指针函数与函数调用机制内存布局图
- 函数指针与指针函数---应用为函数的回调
- c++虚函数的前奏--函数指针与回调
- 指针函数与函数指针
- 指针函数与函数指针
- 函数指针与指针函数
- 指针函数与函数指针
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针 与 指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- Linux创建软链接命令-ln -s
- 删除Xcode中多余的证书provisioning profile
- Mac下搭建Android开发环境
- nginx学习笔记五(nginx的事件模块定义)
- iOS学习之—— initWithFrame的理解
- 函数指针与回调机制
- 浅谈设计模式之访问者模式
- Linux Shell变量使用
- java解析json数组
- 18个开源的Java CMS
- 部署hadoop2.7.2 集群 基于zookeeper配置HDFS HA+Federation
- c++ 异常
- mysql:索引
- 解决Qt5 Creator无法切换输入法(fcitx)