< SHBrowseForFolder クラス | プロジェクトのブラウズ情報を更新する >

March 31, 2004

派生クラスのメンバ関数のポインタ

MFC の CWinThread をカプセル化するクラスを作ろうと思ったのが始まりだったのですが、AfxBeginThread に、派生クラスのメンバ関数は、たとえstatic であっても渡せないようです。ポインタのサイズが違うらしいんですね。(参考: ロベールのC++教室 - 第58章 メンバ関数ポインタ天国 -)

カプセル化したいのはワーカスレッドだったのですが、結局、こんな感じで落ち着きました。以下、基本クラスのヘッダファイルと実装ファイルです。

// MyThread.h: ワーカースレッドのラッパクラス
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MYTHREAD_H__F7F40085_1ED7_4C5F_AA67_A72835BFBE04__INCLUDED_)
#define AFX_MYTHREAD_H__F7F40085_1ED7_4C5F_AA67_A72835BFBE04__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <vector>
#include <afxmt.h>

class CMyThread  
{
public:
	CMyThread();
	virtual ~CMyThread();
	
	static UINT WaitForAllThread();
	static void SetMaxThread( UINT uMaxThread );
	
	UINT Begin();
	friend UINT MapThreadProc( LPVOID lpParam );

protected:
	virtual UINT ThreadProc( LPVOID lpParam )	= 0;	// ワーカスレッドのメイン処理
	static std::vector<CMyThread*>	sm_vecInstances;
	static UINT						sm_uCounter;
	static CCriticalSection			sm_CriticalSection;
	static UINT						sm_uMaxThread;

	HANDLE		m_hThread;
	CWinThread*	m_lpThread;
	BOOL		m_fEndThread;

};

#endif // !defined(AFX_MYTHREAD_H__F7F40085_1ED7_4C5F_AA67_A72835BFBE04__INCLUDED_)
// MyThread.cpp: CMyThread クラスのインプリメンテーション
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MyThread.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

std::vector<CMyThread*>		CMyThread::sm_vecInstances;
UINT						CMyThread::sm_uCounter			= 0;
CCriticalSection			CMyThread::sm_CriticalSection;
UINT						CMyThread::sm_uMaxThread		= 10;


//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////

CMyThread::CMyThread()
	: m_hThread( (HANDLE)NULL )
	, m_lpThread( NULL )
{
	;
}

CMyThread::~CMyThread()
{

}

UINT CMyThread::Begin()
{
	m_lpThread		= AfxBeginThread( ( AFX_THREADPROC )( MapThreadProc ), this );
	m_hThread		= m_lpThread->m_hThread;
	sm_vecInstances.push_back( this );
	return 0;
}

void CMyThread::SetMaxThread( UINT uMaxThread )
{
	sm_uMaxThread	= uMaxThread;
	return;
}

UINT CMyThread::WaitForAllThread()
{
	UINT	num	= sm_vecInstances.size();
	HANDLE	hThreads[MAXIMUM_WAIT_OBJECTS];
	int		iRet		= 0;
	{
		for ( int i = 0; i < num; i++ ) 
			hThreads[ i ] = ( ( CMyThread* )sm_vecInstances[ i ] )->m_hThread;
	}
	switch ( WaitForMultipleObjects( num, hThreads, TRUE, INFINITE ) )
	{
	case WAIT_TIMEOUT:
	case WAIT_FAILED:
		iRet	= 1;
	default:
		;
	}
	return 0;
}

UINT MapThreadProc(LPVOID lpParam)
{
	CMyThread* lpThis = (CMyThread *)lpParam;
	return lpThis->ThreadProc( lpParam );
}

派生クラス側は、CMyThread を継承して、ThreadProc 関数をオーバーライドします。

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/295

コメント

えぇそうなんですか?
静的メンバなら普通の関数ポインタと同じ扱いだと思って
いたんですが、
ところで、
クラスの静的メンバが派生クラスだとサイズが違うだなんて
提示されたロベールに書いてありましたっけ?
(今はリンク切れになってますけど。)
自分の記憶では静的メンバについては触れていなかったような・・・

具体的に試しても問題なさそうでよくわからないし
すごく気になるので
もしよろしければ駄目な例を教えていただけませんか?
ってもう古い記事だし見ていないか・・・

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?