Frage

Im Grunde habe ich die folgende Klasse:

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

Die Methoden stateA () und stateB () sollte in der Lage Rückkehr Zeiger auf stateA sein () und stateB (). Wie die StateMethod typedef?

War es hilfreich?

Lösung

GOTW # 57 sagt für dieses eine Proxy-Klasse mit einer impliziten Konvertierung zu verwenden Zweck.

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;
}
  

Diese Lösung besteht aus drei Haupt   Stärken:

     
      
  1. Es löst das Problem, wie erforderlich. Besser noch, es ist typsicher und   tragbar.

  2.   
  3. Die Maschinen sind transparent: Sie natürliche Syntax für das bekommen   Anrufer / Benutzer und natürliche Syntax für   die Funktion der eigenen „stateA zurückkehren;“   Aussage.

  4.   
  5. Es hat wahrscheinlich Null-Overhead: Auf modernen Compilern, die Proxy-Klasse,   mit seiner Lagerung und Funktionen, sollte   Inline- und optimiert weg wie nichts.

  6.   

Andere Tipps

Mit nur 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); }  

};    

EDIT: njsf bewiesen mich hier falsch. Sie können feststellen, statische einfache Gießen, aber zu halten, so dass ich den Rest hier lassen.

Es gibt keine 'richtige' statischen Typ seit der vollständigen Typ ist rekursiv:

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

Ihre beste Wette ist typedef void (StateMachine::*StateMethod)(); verwenden Sie dann die hässliche state = (StateMethod)(this->*state)();

PS: boost::function einen expliziten Rückgabetyp erfordert, zumindest aus meiner Lektüre der docs : boost::function0<ReturnType>

Meine Philosophie ist Rohglied Funktionszeiger nicht verwenden. Ich weiß nicht einmal wirklich wissen, wie zu tun, was Sie Rohzeiger verwenden wollen TYPEDEF die Syntax ist, ist so schrecklich. Ich mag mit boost :: function.

Das ist fast sicher falsch:

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); }
};

Dieses Problem ist auf jeden Fall viel schwieriger als trifft zuerst das Auge

Ich kann nie die schreckliche C ++ Funktion declspec erinnern, so, wenn ich die Syntax herauszufinden muß, die eine Elementfunktion, beispielsweise beschreibt, habe ich ein absichtlichen Compiler-Fehler nur induzieren, die in der Regel zeigen die korrekte Syntax für mich.

So gegeben:

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

Was ist die Syntax für stateA des typedef? Keine Ahnung .. also lassen Sie uns versuchen, es etwas in keinem Zusammenhang und sehen zuweisen, was der Compiler sagt:

char c = StateMachine::stateA

Compiler sagt:

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

Da ist es. "Bool (State :: *) (int)" ist unser typedef

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top