您的位置:首页 > 其它

让静态成员函数具有多态性(浅谈如何使回调函数具有多态性)

2006-08-11 12:54 471 查看
// 在Windows编程中,经常要用到回调函数.要封装具有回调函数的对象
//就将回调函数设为类的静态成员函数,而在C++中,静态成员函数是没有多态性的.
//如何使静态函数具有"多态性的行为"呢,下面通过封装thread来说明这一技巧

//主要体现在static unsigned int __stdcall ThreadProxy( void *pvParam )
//和int Create()两个函数上面

//MyThread.h
#pragma once
typedef unsigned(__stdcall *pThreadFunc)(void*);
#define smBeginThread(psa,cbStack,pfnStartAddr,pvParam, /
dwCreate,pdwThreadId) /
(HANDLE)_beginthreadex(psa,(unsigned int)cbStack, /
(pThreadFunc)pfnStartAddr,(void*)pvParam,dwCreate,(unsigned*)pdwThreadId)
class CMyThread
{
private:
//禁止拷贝和将对象赋值给其他对象
CMyThread(CMyThread&);
CMyThread & operator =(CMyThread&);
private:
static unsigned int __stdcall ThreadProxy( void *pvParam );
protected:
virtual int Run(void *pvParam)=0;
~CMyThread(void); //使对象只能从堆中创建
protected:
HANDLE _hThread;
public:
enum _DESTROY_TYPE{_dtWAIT=0, //阻塞等待线程直到线程退出
_dtTRY, //如果线程已经退出,则删除,否则立刻返回
_dtTERMINATE}; //强制关闭线程

public:
CMyThread(void);

int Create(LPVOID pvParam,DWORD dwCreate=CREATE_SUSPENDED
,LPSECURITY_ATTRIBUTES psa=NULL,SIZE_T cbStack=0
,LPDWORD pdwThreadId=NULL);
int Suspend();
int Resume();
int Terminate( DWORD dwExitCode);
//当_hThread==NULL,立刻返回-1; 不开预料的错误:返回-2
//当成功删除,返回0,否则返回STILL_ACTIVE
int Destroy(_DESTROY_TYPE dt,DWORD & dwExitCode,DWORD const dwWaitTimes);
BOOL GetExitCode(DWORD &dwExitCode);
HANDLE GetHandle();
DWORD GetId();

};

//MyThread.cpp

#include "StdAfx.h"
#include <Windows.h>
#include <process.h>
#include "./mythread.h"
#ifndef ASSERT
#include <cassert>
#define ASSERT(s) assert(s)
#endif
namespace
{
class _ThreadProxy
{
friend CMyThread;
_ThreadProxy(_ThreadProxy&);
_ThreadProxy& operator =(_ThreadProxy);
private:
CMyThread* _pThis;
void *_pvParam;
_ThreadProxy(CMyThread*thread,void *pvParam)
:_pThis(thread)
,_pvParam(pvParam)
{
}
};
}
CMyThread::CMyThread(void)
:_hThread(0)
{
}

CMyThread::~CMyThread(void)
{
if (_hThread)
{
CloseHandle(_hThread);
}
_hThread=NULL;
}
unsigned int CMyThread::ThreadProxy( void *pvParam )
{
_ThreadProxy *proxy=(_ThreadProxy*)pvParam;
ASSERT(proxy);
CMyThread*pThis=proxy->_pThis;
void *param=proxy->_pvParam;
delete proxy;
return (unsigned int)pThis->Run(param);
}

int CMyThread::Create(LPVOID pvParam,DWORD dwCreate/* =CREATE_SUSPENDED */,
LPSECURITY_ATTRIBUTES psa/* =NULL */
,SIZE_T cbStack/* =0 */,LPDWORD pdwThreadId/* =NULL */)
{
_hThread=smBeginThread(psa,cbStack,ThreadProxy,
(new _ThreadProxy(this,pvParam)) ,dwCreate,pdwThreadId);
ASSERT(_hThread);
return _hThread?0:-1;
}
int CMyThread::Suspend()
{
ASSERT(_hThread);
return ::SuspendThread(_hThread);
}
int CMyThread::Resume()
{
ASSERT(_hThread);
return ::ResumeThread(_hThread);
}
int CMyThread::Terminate( DWORD dwExitCode)
{
ASSERT(_hThread);
return ::TerminateThread(_hThread,dwExitCode);
}
HANDLE CMyThread::GetHandle()
{
return _hThread;
}
DWORD CMyThread::GetId()
{
ASSERT(_hThread);
return ::GetThreadId(_hThread);
}
BOOL CMyThread::GetExitCode(DWORD & dwExitCode)
{
ASSERT(_hThread);
return ::GetExitCodeThread(_hThread,&dwExitCode);
}

//当_hThread==NULL,立刻返回-1; 不开预料的错误:返回-2
//当成功删除,返回0,否则返回返回1
int CMyThread::Destroy(_DESTROY_TYPE dt,DWORD & dwExitCode,
DWORD const dwWaitTimes/* =0 */)
{
int iRet;
if (!_hThread)
{
delete this;
return -1;
}
switch(dt) {
case _dtTRY:
if (GetExitCodeThread(_hThread,&dwExitCode)==0){return -2;}
if (dwExitCode==STILL_ACTIVE) { return 1;}
break;

case _dtWAIT:
ASSERT(dwWaitTimes>=0);
iRet=WaitForSingleObject(_hThread,dwWaitTimes);
if (iRet==WAIT_TIMEOUT)
{
dwExitCode=STILL_ACTIVE;
return 1;
}
if (iRet=WAIT_OBJECT_0)
{
GetExitCodeThread(_hThread,&dwExitCode);
}
break;
case _dtTERMINATE:
if (::GetExitCodeThread(_hThread,&dwExitCode)==0){return -2;}
if (dwExitCode==STILL_ACTIVE)
{
::TerminateThread(_hThread,dwExitCode);
}
break;
}
delete this;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: