問題的由來
C回調(diào)的步驟一般是:
- 聲明callback函數(shù)類型损痰;
- 根據(jù)類型定義一個callback函數(shù)A秒咐;
- 把定義的函數(shù)A股囊,作為參數(shù)傳入到另外一個函數(shù)B潮饱;
- 函數(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)成員的限制穷娱,有了對象之后,你就可以為所欲為啦~