C函數(shù)回調(diào)(callback)C++類成員函數(shù)的方法

問題的由來

C回調(diào)的步驟一般是:

  1. 聲明callback函數(shù)類型损痰;
  2. 根據(jù)類型定義一個callback函數(shù)A秒咐;
  3. 把定義的函數(shù)A股囊,作為參數(shù)傳入到另外一個函數(shù)B潮饱;
  4. 函數(shù)B會在某個時刻蝉衣,調(diào)用A括尸。

因為C里面函數(shù)定義了之后,都是一個全局變量病毡,編譯就會分配好地址濒翻,所以可以很方便的傳遞和使用。

但是在C++里啦膜,情況有點不一樣:
C++的類成員方法即使聲明定義了有送,如果這個類不實例化成對象,那么功戚,類成員方法是不會有地址的娶眷,所以也就無法傳遞給C函數(shù)。
簡單講啸臀,就是你不能使用一個尚且還不存在東東~
那怎么辦呢届宠?


問題的解決

經(jīng)過摸索,目前總結(jié)有兩種方法:

一. 類成員函數(shù)聲明成static函數(shù)

類的static成員講解請看這篇:C++ 類的靜態(tài)成員詳細(xì)講解
聲明成static的類成員函數(shù)乘粒,簡單講豌注,就跟C語言的全局函數(shù)是一個意思,編譯階段就確定好了內(nèi)存地址灯萍,不再依賴對象而存在轧铁,因此使用起來就跟C函數(shù)是一樣的,只不過要這樣:類名::方法()旦棉,要加個前綴齿风。

在VC下的代碼如下:
mythread.h

#ifndef _MY_TEST_H_
#define _MY_TEST_H_

class TestClass {
public:
    TestClass();
    ~TestClass();

    static void notify(int arg1, int arg2);     // declared as static function

private:
    void callback();
};

#endif

mythread.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "mythread.h"

typedef void * HANDLE;

#define SEMAPHORE HANDLE
#define THREADHANDLE HANDLE
#define THREADPROCESS DWORD WINAPI
#define THREADRETURN 0
#define PTHREADPROCESS LPTHREAD_START_ROUTINE
#define NULLTHREAD NULL

int g_thread_end = 0;

TestClass::TestClass() {

}

TestClass::~TestClass() {

}

void TestClass::notify(int arg1, int arg2) {
    printf("notify() is called!\n");
    //callback();                              // static function cannot call no-static function 
}

void TestClass::callback() {
    printf("callback() is called!\n");
}


THREADHANDLE os_creatthread(PTHREADPROCESS fun,void *para)
{
    unsigned long id;
    return CreateThread(NULL,0,fun,para,0,&id);
}

void waitforthread()
{
    while (g_thread_end == 0)
    {
        NULL;
    }   
}

typedef void(*testCb)(int arg1, int arg2);

THREADPROCESS threadfun(PVOID arg)
{
    int i;
    testCb mC;
        
    mC = (testCb)arg;

    for(i=0; i < 50; i++)
    {
        printf("%02d: ", i);
        mC(0, 0);                                   // callback is called!
        Sleep(500);
    }
 
    g_thread_end = 1;
    return 0;
}

void main()
{
    THREADHANDLE pthread = NULLTHREAD;

    printf("Creating thread...\n");
    pthread = os_creatthread(threadfun, TestClass::notify);     // new a thread and register callback
    printf("Creating thread completed.Handle:%x\n", pthread);
    
    printf("Waiting for thread...\n");
    waitforthread();
    
    printf("Waiting ended.\n");

}

注釋應(yīng)該寫的很清楚了:)
要注意的一點是:

  • 靜態(tài)函數(shù)是無法訪問類的非靜態(tài)成員的

二. 傳遞對象

基于一切皆對象的觀點药薯,既然不能直接傳函數(shù),那我們就傳對象好了嘛~
請看代碼:
mythread.h:

#ifndef _MY_TEST_H_
#define _MY_TEST_H_

class TestClass {
public:
    TestClass();
    ~TestClass();

    void notify();

private:
    void callback();
};

#endif

mythread.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "mythread.h"

typedef void * HANDLE;

#define SEMAPHORE HANDLE
#define THREADHANDLE HANDLE
#define THREADPROCESS DWORD WINAPI
#define THREADRETURN 0
#define PTHREADPROCESS LPTHREAD_START_ROUTINE
#define NULLTHREAD NULL

int g_thread_end = 0;

TestClass::TestClass() {

}

TestClass::~TestClass() {

}

void TestClass::notify() {
    printf("notify() is called! -> ");
    callback();
}

void TestClass::callback() {
    printf("callback() is called!\n");
}


THREADHANDLE os_creatthread(PTHREADPROCESS fun,void *para)
{
    unsigned long id;
    return CreateThread(NULL,0,fun,para,0,&id);
}

void waitforthread()
{
    while (g_thread_end == 0)
    {
        NULL;
    }   
}

THREADPROCESS threadfun(PVOID arg)
{
    int i;
    TestClass *mC;
        
    mC = (TestClass *)arg;

    for(i=0; i < 50; i++)
    {
        printf("%02d: ", i);
        mC->notify();                                       // callback function is calling
        Sleep(500);
    }
 
    g_thread_end = 1;
    return 0;
}

void main()
{
    THREADHANDLE pthread = NULLTHREAD;

    TestClass *myClass = new TestClass();                   // firstly, new an object

    printf("Creating thread...\n");
    pthread = os_creatthread(threadfun, myClass);           // register this object as callback
    printf("Creating thread completed.Handle:%x\n", pthread);
    
    printf("Waiting for thread...\n");
    waitforthread();
    
    printf("Waiting ended.\n");

    delete myClass;
}

OK救斑,說完了童本,兩種方法哪種更好用,我目前還挺喜歡第二種的脸候,因為沒有只能訪問靜態(tài)成員的限制穷娱,有了對象之后,你就可以為所欲為啦~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末运沦,一起剝皮案震驚了整個濱河市泵额,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌携添,老刑警劉巖嫁盲,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異薪寓,居然都是意外死亡亡资,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門向叉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锥腻,“玉大人,你說我怎么就攤上這事母谎∈莺冢” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵奇唤,是天一觀的道長幸斥。 經(jīng)常有香客問我,道長咬扇,這世上最難降的妖魔是什么甲葬? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮懈贺,結(jié)果婚禮上经窖,老公的妹妹穿的比我還像新娘。我一直安慰自己梭灿,他們只是感情好画侣,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著堡妒,像睡著了一般配乱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天搬泥,我揣著相機(jī)與錄音桑寨,去河邊找鬼。 笑死佑钾,一個胖子當(dāng)著我的面吹牛西疤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播休溶,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扰她!你這毒婦竟也來了兽掰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤徒役,失蹤者是張志新(化名)和其女友劉穎孽尽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忧勿,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡杉女,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸳吸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熏挎。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖晌砾,靈堂內(nèi)的尸體忽然破棺而出坎拐,到底是詐尸還是另有隱情,我是刑警寧澤养匈,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布哼勇,位于F島的核電站,受9級特大地震影響呕乎,放射性物質(zhì)發(fā)生泄漏积担。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一猬仁、第九天 我趴在偏房一處隱蔽的房頂上張望帝璧。 院中可真熱鬧,春花似錦逐虚、人聲如沸聋溜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撮躁。三九已至,卻和暖如春买雾,著一層夾襖步出監(jiān)牢的瞬間把曼,已是汗流浹背杨帽。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留嗤军,地道東北人注盈。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像叙赚,于是被迫代替她去往敵國和親老客。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容