C++中回调的实现

作者: NiceBlueChai | 来源:发表于2017-10-04 22:44 被阅读79次

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_H

class 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 long
inline 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;
}

❤️我的目标是:someday,即便你花钱看我的文章,也会觉得心满意足


相关文章

  • 在 WebAssembly 中实现回调的方式

    本文将介绍在 C++ 中实现 js 回调的几种方式. 在使用 wasm 的过程中, 避免不了要从 C++ 回调 j...

  • c++11 之回调函数

    什么是回调函数,以及在c++中如何使用? 回调函数就是将函数 作为参数传给其他的函数。 c++ 中有三种方式实现:...

  • C++中回调的实现

    C++中使用class语法实现回调(当然,,旧式的C函数指针回调也是支持的) 比如,有人提供一个类库 AfCopy...

  • java回调函数

    利用接口来实现回调,即在调用回调函数的类中实现接口,并实现接口中的方法即回调的方法,被调用类中存在接口的熟悉,并将...

  • Kotlin使用接口回调

    1.Java中的接口回调实现(支持多方法回调) 声明回调接口,初始化接口 使用接口回调(无参数) 使用接口回调(带...

  • 回调函数简介

    C++回调函数相关 1. 首先还是由最基本的"Hello World!"程序引入 2. 接下来实现一个简单的函数调...

  • Springboot实战系列之@Autowired注入类的lis

    一个回调接口有多种回调逻辑,在项目启动时需要将回调接口的实现类都放到一个list中然后回调每个实现类的具体方法。在...

  • MediaCodec解码FFmpeg AvPacket

    VideoSupportUtil.java c++层: 解码AvPacket数据 c++层回调decodeAVPa...

  • Java回调实现

    Java回调实现 什么是回调 回调核心思想 案例代码实现 后序 一、什么是回调 开发过程当中存在某种特殊的业务需求...

  • 10 泛型库

    回调 回调的含义是:对一个库,用户希望库能够调用用户自定义的某些函数,这种调用称为回调。C++中用于回调的类型统称...

网友评论

本文标题:C++中回调的实现

本文链接:https://www.haomeiwen.com/subject/ndmcyxtx.html