C++において、コールバックの方法例をどのように実現しますか?


前言
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 %%
", user, source, dst, percent); return 0; } private: char source[256]; char dst[256]; char user[64]; }; int main() { MainJob job; job.DoJob(); return 0; }
締め括りをつける
以上がこの文章の全部です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。