
| 
\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; と明示する必要あり.
POINT
     クラスのメンバ関数の型を typedef する。
     関数ポインタ型の構文はわかりずらいので typedef で別名をつけると便利。
     コンパイラに void T::( void ); 型を FuncPtr であると教える。
    class Foo
    {
      public:
        void func();
    };
      #typedef void ( T::*FuncPtr)();
WARNING 
    C スタイルの関数ポインタを必要とする場所で、 メンバ関数ポインタを渡すことはできない。
    この場合は , 静的メンバ関数、または非メンバ関数を利用する。
    シグナルハンドラ
      {
      // p はメンバ関数を指すためのポインタ変数。
       FuncPtr p;
        // メンバ関数ポインタにメンバ関数をセットする
       p = T::func();     
       p = &T::func();     
      
       // コールするときは this に渡すインスタンスからよびだす。
       class obj;
       (obj.*p)();         
スタティックメンバ関数ならば 呼び出し規約は同じになるので
    C スタイルの関数ポインタと互換性がある。
    #include< signal.h> 
    int main() {
      // 静的メンバメソッドならば渡すことができる
      signal( SIGINT, Test::signalHandler );
    }
    // グローバル変数経由でわたす インスタンスを取得して メンバ関数をよびだす
■ ステートパターン内で利用する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