9

基本上我有以下课程:

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

stateA() 和 stateB() 方法应该能够返回指向 stateA() 和 stateB() 的指针。如何键入定义StateMethod?

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

该解决方案具有三个主要优势:

  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 回答