トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
C++
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索

___

■ メンバー関数ポインタ

  


    次のように展開するとわかりやすい

    メンバ関数は通常の C スタイルの関数とはシグネーチャが異なる。
    暗黙の this ポインタをもつ。


       func : Foo::memberFunc() を指す Ptr なので, Foo に func() という FuncMem がなくても OK.
       object->*func() === object->(*func)() === object->memberFunc()

    C3837 :
       FuncMem の アドレスを渡す場合は, &Foo::func; と明示する必要あり.

    class Foo
    {
      public:
        void func();
    };
POINT クラスのメンバ関数の型を typedef する。 関数ポインタ型の構文はわかりずらいので typedef で別名をつけると便利。 コンパイラに void T::( void ); 型を FuncPtr であると教える。
      #typedef void ( T::*FuncPtr)();
      {
      // p はメンバ関数を指すためのポインタ変数。
       FuncPtr p;

        // メンバ関数ポインタにメンバ関数をセットする
       p = T::func();     
       p = &T::func();     

      
       // コールするときは this に渡すインスタンスからよびだす。
       class obj;
       (obj.*p)();         

WARNING C スタイルの関数ポインタを必要とする場所で、 メンバ関数ポインタを渡すことはできない。 この場合は , 静的メンバ関数、または非メンバ関数を利用する。 シグナルハンドラ

    #include< signal.h> 

    int main() {
      // 静的メンバメソッドならば渡すことができる
      signal( SIGINT, Test::signalHandler );
    }

    // グローバル変数経由でわたす インスタンスを取得して メンバ関数をよびだす


スタティックメンバ関数ならば 呼び出し規約は同じになるので C スタイルの関数ポインタと互換性がある。
___

■ ステートパターン内で利用する

POINT 動作を表す変数( 動作もまた情報 ) -> ex. stateFunc ( 動作名をいれよう ) -> 応用例( FSM ) class obj { protected: // 状態別 mem 関数の宣言: typedef void (obj::*stateFunc)(); // objCls の funcPtr( 内部的には obj_stateFunc() ) // それを保持する変数 stateFunc statFn; private: // 状態別関数 void state1() { printf("do state1\n"); this->statFn = state2; } void state2() { printf("do state2\n"); this->statFn = state1; // cls 名を指定しなくても OK } public: Obj(){ stateFunc() = state1; } // update 処理では状態関数を呼ぶだけ inline void update(){ (this->*statFn)(); } }; { switch ( state ){ case STATE1: state1(); break; case STATE2: state2(); break; } } typedef void (T_Class::*SetParamProc)( const T_Param &val ); typedef const T_Param &(T_Class::*GetParamProc)(); // メンバ関数ポインタ を用いた todo 処理の例 class TestCls { /* TestCls の関数か, global関数かを cmp に通知 */ typedef void (TestCls::*Func)(); public: // todo 一覧 void foo(){ printf("foo") }; void bar(){ printf("bar") }; TestCls(){ /* TestCls の foo() を渡すことを通知. ( & は任意 ) */ todoList.push_back( &TestCls::goo ); } vector< Func > todoList; void action(){ int i; for( i=0; i< todoList.size(); i++ ){ Func p = todoList[i]; /* 呼ぶときは, どの inst かを通知 */ (this->*p)(); } }; }; DESC 通常 typedef void (*func)(); cls typedef void (clsName::*func)(); // void clsName::func() 型の funcPtr 関数 ptr の ads を渡すには ... 通常 void foo(){ ... } func a = foo; cls typedef void (clsName::*func)(); // void clsName::func() 型の funcPtr void clsName::bbb(){ ... } 関数 ptr を param とする function は // template cls にすると, 関数の型を以下のように可変にできる void setClassInfo( T_Class &inst, SetParamProc set, GetParamProc get, std::string _name = "" ); template< class T_Class, class T_Param> // この cls の この param という class Test : public TestValue< T_Param> { private: }; // 渡し方 // & をつける POINT template化 cls は cls 生成の時点で template 指定するが、 mem 関数 は 通常とおり使用できる. 関数ポインタに格納する関数は, [ class 名 ]も同一でなくてはならない。 派生先の関数でも格納は不可能( 派生先しかない情報にアクセスされたらOUT ) この場合は, virtual bcls::todoXXX(){} として枠組みをつくって, 派生先で 必要な処理を overwrite することで OK もしくは, 各クラスで todo 処理をするふるまい [ actionTodo() ] を作成する template ということは, class 名の部分を置換してやれば可能。

NINJAIDX 12