首页 > 编程 > C++ > 正文

C++中如何实现回调的方法示例

2020-05-23 13:45:24
字体:
来源:转载
供稿:网友

前言

C++中使用class语法实现回调(当然,,旧式的C函数指针回调也是支持的)

比如,有人提供一个类库 AfCopyFile,能够提供文件拷贝的功能,而且能通知用户当前的进度。。。

int DoCopy(const char* source,const char* dst,AfCopyFileListener* listener);

用户只需要自己实现一个AfCopyFileListener对象,传给这个函数就行。。。

class MainJob : public AfCopyFileListener{int OnCopyProgress(long long total,long long transfered){ }}

把Listener对象传过去

AfCopyFile af;af.DoCopy(source, dst, this); 

回调机制的缺点:

无论是C语言的回调函数,还是C++里的Listener,都有一个共同的缺点:

它使代码逻辑变得难以阅读。。

我们应尽量避免使用回调机制,最好采用单向的函数调用。

示例代码:

AfCopyFile.h

#ifndef _AF_COPY_FILE_H#define _AF_COPY_FILE_Hclass AfCopyFile{public: // 作为内部类 class Listener { public:  virtual int OnCopyProgress(long long total, long long transfered) = 0; };public: int DoCopy(const char* source, const char* dst, Listener* listener);};#endif

AfCopyFile.cpp

#include <stdio.h>#include <Windows.h>#include "AfCopyFile.h"// 将LARGE_INTTEGER类型转成unsigned long longinline unsigned long long translate(LARGE_INTEGER num){ unsigned long long result = num.HighPart; result <<= 32; result += num.LowPart; return result;}// 回调函数// 注:要求将此函数用关键字CALLBACK修饰(这是Windows API的要求)static 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) // <- 这个就是上下文件对象{ // 计算百分比 unsigned long long total = translate(TotalFileSize); unsigned long long copied = translate(TotalBytesTransferred); // 打印进度 AfCopyFile::Listener* listener = (AfCopyFile::Listener*) lpData; listener->OnCopyProgress(total, copied); return PROGRESS_CONTINUE;}int AfCopyFile::DoCopy(const char* source, const char* dst, Listener* listener){ BOOL ret = CopyFileEx(source, dst,  &CopyProgress, // 待回调的函数  listener,  // 上下文对象  NULL, 0);  return ret ? 0 : -1;}

main.cpp

#include <stdio.h>#include <string.h>#include "AfCopyFile.h"class MainJob : public AfCopyFile::Listener{public: int DoJob() {  strcpy(user, "shaofa");  strcpy(source, "c://test//2.rmvb" );  strcpy(dst, "c://test//2_copy.rmvb");  AfCopyFile af;  af.DoCopy(source, dst, this); // 将this传过去   return 0; } 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; }private: char source[256]; char dst[256]; char user[64];};int main(){ MainJob job; job.DoJob(); return 0;}

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对VEVB武林网的支持。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表