[PR]プロが競馬の全てを教えます:勝てる競走馬情報で万馬券GET!


C++で擬似タスクは失敗かな〜

前回C++で擬似タスクシステムの雛型を設計してみましたが, もぅ,この段階でいろいろ問題点が浮上!!
(TдT)あぁ〜ぁ

問題点:処理関数に仮想関数を適応したところ

ここでは,「毎フレームにタスクが行う処理をまとめた関数」を処理関数と呼んでます.
何を勘違いしたか,「1タスク1処理関数」と思ってしまったために,
本来関数ポインタで実装される処理関数を仮想関数として実装してしまいました.

関数ポインタで実装している場合は,タスク内のデータを保持したまま
簡単に処理だけを切り替えることができます.
(ポインタを変更するだけなんで)
仮想関数はクラスごとに設定されているので,処理を変更するには,
クラスの変更をしないといけないです.
クラスを変更ってことは,データを保持したままにできないじゃん(TДT)
だめだめだぁ…

例えば,「ゆっくり出現→弾をばら撒く→ぴゅーっと逃げる」というような敵キャラ
を作った場合なんか,関数ポインタを使わないとなると,
結局は処理ごとに条件分岐しないといけなくなるので,意味無いですねぇ.
まさか,処理変更の度にクラスを変更するなんてことしたくないし.
( ̄ε ̄) ちぇ〜

んー,処理関数として作った仮想関数のなかで,
さらに処理ごとの関数ポインタを使って処理をさせるっていうのも2度手間くさいし…
はじめっから関数ポインタで実装すればよかったかなぁ〜
(できるかどうかわからんけど…)

どうしても処理関数を関数ポインタで実装したい場合の例を考えてみよう.
このタスククラスには処理が3種類あって,1→2→3→1…と遷移していくというもの.
class TaskXXX : public TaskBase 
{
public :
    //-------------------------------------------------------------------------
    //  コンストラクタ
    //  デフォルトの処理関数を設定しておく
    //-------------------------------------------------------------------------
    TaskXXX()
    {
        pFunc = TaskXXX::process1 ;
    }

    //-------------------------------------------------------------------------
    //  タスクの処理関数
    //  (メインルーチンから呼ばれる用)
    //-------------------------------------------------------------------------
    virtual void Process()
    {
        (this->*pFunc)();
    }

private :

    // 処理関数のポインタ
    void (TaskXXX::*pFunc)() ;


    //-------------------------------------------------------------------------
    // 処理関数の変更
    //-------------------------------------------------------------------------
    void ChangeProcess( void (TaskXXX::*p)() )
    {
        pFunc = p ;
    }

    //-------------------------------------------------------------------------
    //  [ 実際の処理関数 ]
    //  ここは,させたい処理が増えるたび,状態が増えるたびに
    //  関数を追加していく.
    //-------------------------------------------------------------------------
    void process1()
    {
        ::printf("TaskBase::process1\n");
        
        ChangeProcess( TaskXXX::process2 );      // 処理変更!
    }

    void process2()
    {
        ::printf("TaskBase::process2\n");

        ChangeProcess( TaskXXX::process3 );
    }

    void process3()
    {
        ::printf("TaskBase::process3\n");

        ChangeProcess( TaskXXX::process1 );
    }
};




int main()
{
    TaskXXX task ;

    task.Process() ;
    task.Process() ;
    task.Process() ;
    task.Process() ;

    getchar();
    return 0 ;
}
実行結果
TaskXXX::process1
TaskXXX::process2
TaskXXX::process3
TaskXXX::process1

うぁ〜,クラス派生させるたびに,毎回かかないといけない処理(しかもほとんどいっしょ)
が多くてメンドくさいなぁ…(TДT)
こんな感じのを,親クラスにだけ書いとけばいいような,うまい解決法はないもんかな〜
テンプレート使ったところで,クラスを増やすたびに,最終的に関数ポインタが
増えまくりそうなので,どうもダメくさいしなあぁ…




<< Back to Diary...

[PR]看護師の求人をお探しなら:〈マイナビ看護師〉完全無料