9

基本的に私は次のクラスを持っています:

class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};

メソッド stateA() および stateB() は、stateA() および stateB() へのポインターを返すことができる必要があります。StateMethod を typedef する方法は?

4

5 に答える 5

14

GotW #57では、まさにこの目的のために、暗黙的な変換でプロキシ クラスを使用するように指示されています。

struct StateMethod;
typedef StateMethod (StateMachine:: *FuncPtr)(); 
struct StateMethod
{
  StateMethod( FuncPtr pp ) : p( pp ) { }
  operator FuncPtr() { return p; }
  FuncPtr p;
};

class StateMachine {
  StateMethod stateA();
  StateMethod stateB();
};

int main()
{
  StateMachine *fsm = new StateMachine();
  FuncPtr a = fsm->stateA();  // natural usage syntax
  return 0;
}    

StateMethod StateMachine::stateA
{
  return stateA; // natural return syntax
}

StateMethod StateMachine::stateB
{
  return stateB;
}

このソリューションには、主に次の 3 つの強みがあります。

  1. 必要に応じて問題を解決します。さらに良いことに、タイプセーフで移植性があります。

  2. その機構は透過的です。呼び出し元/ユーザーの自然な構文と、関数自体の「return stateA;」の自然な構文が得られます。声明。

  3. オーバーヘッドはおそらくゼロです。最新のコンパイラでは、ストレージと関数を備えたプロキシ クラスをインライン化し、最適化してゼロにする必要があります。

于 2008-10-02T05:55:36.253 に答える
8

typedefだけを使用:

class StateMachine {  

 public:  

  class StateMethod;     
  typedef StateMethod (StateMachine::*statemethod)();   

  class StateMethod {  

    statemethod   method; 
    StateMachine& obj; 

   public:  

    StateMethod(statemethod method_, StateMachine *obj_)  
      : method(method_), obj(*obj_) {} 

    StateMethod operator()() { return (obj.*(method))(); }  
  };  

  StateMethod stateA()  { return StateMethod(&StateMachine::stateA, this); }  

  StateMethod stateB()  { return StateMethod(&StateMachine::stateB, this); }  

};    
于 2008-10-02T05:56:21.057 に答える
3

編集: njsf は、ここで私が間違っていることを証明しました。ただし、静的キャストを維持する方が簡単だと思うかもしれませんので、残りはここに残します。

完全な型は再帰的であるため、「正しい」静的型はありません。

typedef StateMethod (StateMachine::*StateMethod)();

あなたの最善の策は、使用typedef void (StateMachine::*StateMethod)();してから醜いことをすることですstate = (StateMethod)(this->*state)();

PS:boost::function少なくともドキュメントを読んだことから、明示的な戻り値の型が必要です:boost::function0<ReturnType>

于 2008-10-02T05:46:10.440 に答える
2

私の哲学は、生のメンバー関数ポインターを使用しないことです。生のポインター typedef の構文を使用して必要なことを行う方法が本当にわかりません。構文は非常に恐ろしいです。boost::function を使用するのが好きです。

これはほぼ確実に間違っています。

class X
{
  public:
    typedef const boost::function0<Method> Method;

    // some kind of mutually recursive state machine
    Method stateA()
    { return boost::bind(&X::stateB, this); }
    Method stateB()
    { return boost::bind(&X::stateA, this); }
};

この問題は、最初に目にしたよりもはるかに難しいことは間違いありません

于 2008-10-02T05:27:46.677 に答える
0

私はひどい C++ 関数の declspec を覚えていないので、たとえばメンバー関数を記述する構文を見つけなければならないときはいつでも、通常は正しい構文を表示する意図的なコンパイラ エラーを引き起こすだけです。

与えられた:

class StateMachine { 
    bool stateA(int someArg); 
};

stateA の typedef の構文は何ですか? わからない..だから、それに無関係なものを割り当てて、コンパイラが何を言っているか見てみましょう:

char c = StateMachine::stateA

コンパイラは次のように述べています。

error: a value of type "bool (StateMachine::*)(int)" cannot be used to initialize 
       an entity of type "char" 

「bool (StateMachine::*)(int)」は typedef です。

于 2008-10-02T17:52:09.027 に答える