C++で擬似タスクに挑戦
はぬぅーん.い…忙しい!!
void キャラごとの処理()
{
switch( キャラのタイプ )
{
case ジゴロ :
ジゴロビーム();
break ;
case おねぇ:
フェロモンビーム();
break ;
case 幼女:
もえもえビーム();
break ;
}
}
↓変更!
void キャラごとの処理()
{
キャラタスク->ビーム()
}
みたいな感じになったりするんじゃないかなぁ〜TaskList.Add( new EnemyTask() );みたいな感じで,タスクを追加できるといいかなー.
// メモリ確保すると,自動的にタスクに追加 TaskBase * pTask = new EnemyTask(); // 開放すると自動的にタスクからハズされる delete pTask ;ってな感じで,自動的にタスクに追加されると便利…かも(?)
#include <stdio.h>
#include <stdlib.h>
///////////////////////////////////////////////////////////////////////////////
//
// new 演算子のオーバライド実験用の,派生元クラス
//
///////////////////////////////////////////////////////////////////////////////
class NewTestBase
{
public :
//-------------------------------------------------------------------------
// new
//-------------------------------------------------------------------------
void * operator new ( size_t size )
{
printf( " NewTestBaseサイズ:%d\n", sizeof(NewTestBase) );
printf( " 確保サイズ:%d\n", size );
return malloc( size );
}
//-------------------------------------------------------------------------
// delete
//-------------------------------------------------------------------------
void operator delete( void * p )
{
printf( " NewTestBase開放\n" );
free( p );
}
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
NewTestBase()
{
printf(" NewTestBase::コンストラクト\n");
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
virtual ~NewTestBase()
{
printf(" NewTestBase::デストラクト\n");
}
//-------------------------------------------------------------------------
// 実験用〜
//-------------------------------------------------------------------------
virtual void move()
{
printf(" NewTestBase.a = %d\n", a );
}
protected :
int a, b, c ;
};
///////////////////////////////////////////////////////////////////////////////
//
// new 演算子のオーバライド実験用の,派生クラス
//
///////////////////////////////////////////////////////////////////////////////
class NewTestChild : public NewTestBase
{
public :
//-------------------------------------------------------------------------
// new
//-------------------------------------------------------------------------
void * operator new( size_t size )
{
printf( " NewTestChildのサイズ:%d\n", sizeof(NewTestChild) );
printf( " 確保サイズ:%d\n", size );
return malloc( size );
}
//-------------------------------------------------------------------------
// delete
//-------------------------------------------------------------------------
void operator delete( void * p )
{
printf( " NewTestChild開放\n" );
free( p );
}
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
NewTestChild()
{
printf(" NewTestChild::コンストラクタ\n");
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
virtual ~NewTestChild()
{
printf(" NewTestChild::デストラクタ\n");
}
//-------------------------------------------------------------------------
// テスト〜
//-------------------------------------------------------------------------
virtual void move()
{
printf(" NewTestChild.c = %d\n", c );
}
private :
int c, d, e ;
};
///////////////////////////////////////////////////////////////////////////////
//
// Main
//
///////////////////////////////////////////////////////////////////////////////
int main()
{
// もともとのクラスで実験
printf("-- 派生元クラス --\n");
NewTestBase * ptest = new NewTestBase();
ptest->move();
delete ptest ;
// 派生クラスで実験
printf("\n-- 派生クラス --\n");
ptest = new NewTestChild();
ptest->move();
delete ptest ;
getchar();
return 0 ;
}
…で,これ↓が実行結果.
-- 派生元クラス --
NewTestBaseサイズ:16
確保サイズ:16
NewTestBase::コンストラクト
NewTestBase.a = -842150451
NewTestBase::デストラクト
NewTestBase開放
-- 派生クラス --
NewTestChildのサイズ:28
確保サイズ:28
NewTestBase::コンストラクト
NewTestChild::コンストラクタ
NewTestChild.c = -842150451
NewTestChild::デストラクタ
NewTestBase::デストラクト
NewTestChild開放
ふむふむ.ちゃんとコンストラクタも呼ばれてるし,期待通りの動作してるな.
-- 派生元クラス --
NewTestBaseサイズ:16
確保サイズ:16
NewTestBase::コンストラクト
NewTestBase.a = -842150451
NewTestBase::デストラクト
NewTestBase開放
-- 派生クラス --
NewTestBaseサイズ:16
確保サイズ:28 ← ちゃんと確保されてる!?
NewTestBase::コンストラクト
NewTestChild::コンストラクタ
NewTestChild.c = -842150451
NewTestChild::デストラクタ
NewTestBase::デストラクト
NewTestBase開放
あ,あれ? 派生元の new と delete がちゃんと呼ばれる!?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define TASK_SIZE 256
#define TASK_NUM 256
///////////////////////////////////////////////////////////////////////////////
//
// タスク用メモリクラス
//
///////////////////////////////////////////////////////////////////////////////
class TaskMemory
{
public :
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
TaskMemory()
{
// ホントはコンストラクタで確保したくないけど…
m_pHeap = (BYTE*)malloc( TASK_SIZE * TASK_NUM );
memset( m_HeapIndex, 0, sizeof(BYTE)*TASK_NUM );
printf("タスクサイズ:%d\n", TASK_SIZE );
printf("最大タスク数:%d\n", TASK_NUM );
printf("ヒープの先頭アドレス:0x%x\n", m_pHeap );
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
~TaskMemory()
{
free( m_pHeap );
}
//-------------------------------------------------------------------------
// 空きタスク領域を得る
//
// [戻り値]
// NULL : 空き領域なし
// それ以外 : タスク領域のポインタ
//
// ここは現在かなりヘボい実装をしてるので,
// うまく改良して高速化するべし!
//-------------------------------------------------------------------------
void * MallocTask()
{
for (int i=0 ; i < TASK_NUM ; ++i )
{
if ( 0 == m_HeapIndex[ i ] )
{
printf( "タスクインデクス[%d], アドレス[0x%x]\n",
i, m_pHeap + (i * TASK_SIZE) );
m_HeapIndex[ i ] = 1 ;
return ( m_pHeap + (i * TASK_SIZE) ) ;
}
}
return NULL ;
}
//-------------------------------------------------------------------------
// タスク領域を開放する
//
// [引数]
// address : 開放(無効化)したいタスク領域のアドレス
//
// delete の実装都合上,インデクスよりもアドレスの方がよかったので.
//-------------------------------------------------------------------------
void FreeTask( const void * const address )
{
int index = ( (BYTE*)address - m_pHeap ) / TASK_SIZE ;
printf("開放するアドレス[0x%x] → インデクス[%d]\n", address, index );
if ( index >= 0 && index < TASK_NUM )
{
m_HeapIndex[ index ] = 0 ;
}
}
private :
BYTE * m_pHeap ; // 仮想ヒープ領域
BYTE m_HeapIndex[ TASK_NUM ] ; // 0 : 未使用 1 : 使用中
};
// 大域変数にしちゃった…
// クラスなんかにせずに,関数だけのモジュールにすればよかったなぁ.
TaskMemory g_TaskMemory ;
///////////////////////////////////////////////////////////////////////////////
//
// タスクのベースクラス
//
///////////////////////////////////////////////////////////////////////////////
class TaskBase
{
public :
//-------------------------------------------------------------------------
// new
//
// size に作成するクラスが必要とするメモリサイズが入ってくるので,
// タスクサイズを超えないかどうかをチェックしとく.
//-------------------------------------------------------------------------
void * operator new ( size_t size )
{
if ( size >= TASK_SIZE )
{
printf("タスクサイズよりも大きなタスクを作成しようとしています\n");
getchar();
return NULL ;
}
return g_TaskMemory.MallocTask();
}
//-------------------------------------------------------------------------
// delete
//-------------------------------------------------------------------------
void operator delete ( void * p )
{
g_TaskMemory.FreeTask( p );
}
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
TaskBase()
{
priority = rand() % 256 ;
printf( " TaskBase::コンストラクタ\n" );
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
virtual ~TaskBase()
{
printf( " TaskBase::デストラクタ\n" );
}
//-------------------------------------------------------------------------
// ちょっと実験用
//-------------------------------------------------------------------------
virtual void ShowPriority()
{
printf( " TaskBase::優先度:%d\n", priority );
}
protected :
// ちゃんと変数にアクセスできるのかな?
int task_ID ;
int priority ;
};
///////////////////////////////////////////////////////////////////////////////
//
// タスクA
//
///////////////////////////////////////////////////////////////////////////////
class TaskA : public TaskBase
{
public :
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
TaskA()
{
printf(" TaskA::コンストラクタ\n");
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
virtual ~TaskA()
{
printf(" TaskA::デストラクタ\n");
}
//-------------------------------------------------------------------------
// 実験〜
//-------------------------------------------------------------------------
virtual void ShowPriority()
{
printf(" TaskA::優先度:%d\n", priority );
}
private :
int pow ;
// ためしに,タスクサイズより大きなクラスを作ろうとすると
// 実行時に警告がでるはず〜
// BYTE dammy[255];
};
///////////////////////////////////////////////////////////////////////////////
//
// タスクB(さらに継承したらどうなるんじゃろ?)
//
///////////////////////////////////////////////////////////////////////////////
class TaskB : public TaskA
{
public :
//-------------------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------------------
TaskB()
{
printf(" TaskB::コンストラクタ\n");
}
//-------------------------------------------------------------------------
// デストラクタ
//-------------------------------------------------------------------------
virtual ~TaskB()
{
printf(" TaskB::デストラクタ\n");
}
//-------------------------------------------------------------------------
// 実験〜
//-------------------------------------------------------------------------
virtual void ShowPriority()
{
printf(" TaskB::優先度:%d\n", priority );
}
};
///////////////////////////////////////////////////////////////////////////////
//
// Main
//
///////////////////////////////////////////////////////////////////////////////
int main()
{
// 実験
TaskBase * pTask1 = new TaskBase();
TaskBase * pTask2 = new TaskA();
pTask1->ShowPriority();
pTask2->ShowPriority();
delete pTask1 ;
delete pTask2 ;
// 継承実験
pTask1 = new TaskB();
pTask1->ShowPriority();
delete pTask1 ;
getchar();
return 0 ;
}
そして,実行結果がこれ↓
タスクサイズ:256
最大タスク数:256
ヒープの先頭アドレス:0x540068
タスクインデクス[0], アドレス[0x540068]
TaskBase::コンストラクタ
タスクインデクス[1], アドレス[0x540168]
TaskBase::コンストラクタ
TaskA::コンストラクタ
TaskBase::優先度:41
TaskA::優先度:35
TaskBase::デストラクタ
開放するアドレス[0x540068] → インデクス[0]
TaskA::デストラクタ
TaskBase::デストラクタ
開放するアドレス[0x540168] → インデクス[1]
タスクインデクス[0], アドレス[0x540068]
TaskBase::コンストラクタ
TaskA::コンストラクタ
TaskB::コンストラクタ
TaskB::優先度:190
TaskB::デストラクタ
TaskA::デストラクタ
TaskBase::デストラクタ
開放するアドレス[0x540068] → インデクス[0]
…なんか,わかりづらいけど,ちゃんと動いてるような気もするなぁ.