スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【コード】クラス内で関数ポインタを使用する

ちょっとだけ苦労したところだったので記事に上げてみました。

題名通り、クラスで関数ポインタを使用してみます。

その1。
関数ポインタを使用して、呼び出す関数を変化させる。

class CSAMPLE
{
private:
void Func01(); // 何かする関数1
void Func02(); // 何かする関数2
void Func03(); // 何かする関数3

void (CSAMPLE::*m_pFunc)(); // 関数ポインタ

// 実行する関数をセットする
void SetFunc(void (CSAMPLE::*pFunc)())
{
m_pFunc = pFunc;
}

public:
// コンストラクタ
CSAMPLE():m_pFunc(&CSAMPLE::Func01){ }

// CSAMPLE::UpDate() を呼ぶことで
// セットされている関数を実行する

void UpDate()
{
(this->*m_pFunc)();
}

};

まず、クラスが定義されるとコンストラクタが呼ばれ、
m_pFunc(関数ポインタ)に、CSAMPLE::Func01 のアドレスがセットされます。

Func01~Func03 は private なメンバ関数なので、外部から呼び出すことはできません。
そこで、public なメンバ関数 UpDate メソッドを使用します。
今 UpDate メソッドを呼ぶと、コンストラクタで初期化された Func01 メソッドが呼ばれます。


例えば、Func01 メソッド内でタイトル画面を制御しているとします。
決定ボタンが押されたら Func02 へ移行するようにしました。

void CSAMPLE::Func01()
{
タイトルの処理();

if(決定ボタンが押されたら)
this->SetFunc(&CSAMPLE::Func02);
}

すると、今度の UpDate メソッドは Func02 が呼ばれるようになります。
呼び出し側は、常に UpDate メソッドを呼ぶ必要はありますが
~の時は Func01 メソッドを、~の時は Func02 メソッドというように
switch~case で分ける必要がなくなります。
個人的に結構便利です。


クラス内でアクセスしているため、ぶっちゃけ SetFunc メソッドは必要ありません。
引数の書き方がちょっと違うので今回は使用しました。



その2。
関数ポインタを配列で。
今度は、上の Func01 ~ Func03 までを配列で持たせてみました。

class CSAMPLE
{
private:
void Func01(); // 何かする関数1
void Func02(); // 何かする関数2
void Func03(); // 何かする関数3

void ( CSAMPLE::*m_pFunc[3] )(); // 関数ポインタの配列

public:
// コンストラクタ
CSAMPLE():m_FuncCount(0)
{
m_pFunc[0] = &CSAMPLE::Func01; // Func01 のアドレスをセット
m_pFunc[1] = &CSAMPLE::Func02; // Func02 のアドレスをセット
m_pFunc[2] = &CSAMPLE::Func03; // Func03 のアドレスをセット
}

// CSAMPLE::UpDate() を呼ぶことで
// セットされている関数を実行する

void UpDate()
{
(this->*m_pFunc[m_FuncCount])();
}

};

今回も UpDate メソッドを呼ぶ所は変わりません。
(this->*m_pFunc[m_FuncCount])(); という所が変わっている部分です。

メソッドの呼び出し方がちょっと変わってますが、
基本的な所は配列の使い方と変わっていません。

コンストラクタが呼ばれた後、
m_pFunc[0]~[2] に各関数のアドレスがセットされています。
そして、m_FuncCount には 0 がセットされています。

今のタイミングで UpDate メソッドを呼ぶと、
m_FuncCount が 0 なので、m_pFunc[0] にセットされたメソッド(Func01)が実行されます。


今度の Func01 は敵の攻撃パターンその1です。
敵が倒されたら次の攻撃パターン(Func02)に移行したいと思います。

void CSAMPLE::Func01()
{
敵の攻撃処理その1();

if(敵が倒されたら)
++m_FuncCount;
}

敵が倒されたら m_FuncCount が足され、UpDate メソッドが呼ばれると
(this->*m_pFunc[1])() を呼ぶことになるので、Func02 メソッドが呼ばれる仕組みです。
今回は配列を3つまでしか確保していないので、m_pFunc[3]以降はアクセス違反になります。


敵の攻撃パターン等、
関数をまとめたい時に関数ポインタの配列を使ってみるのはどうでしょうか。


…と、自分のメモ代わりに残しておきました。

この記事へのコメント

トラックバック

URL :

検索フォーム
プロフィール

DVDM

Author:DVDM
自作ゲームの開発過程ブログ。
赤髪愛なら誰にも負けない。

 
Pixiv バナー


ブロとも申請フォーム
最新記事
カテゴリ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
ブロとも一覧
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。