2008-10-02 4 views
9

В принципе у меня есть следующий класс:Как typedef указатель на метод, который возвращает указатель на метод?

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

методы stateA() и stateB() должны быть в состоянии возвращать указатели на stateA() и stateB(). Как типизировать StateMethod?

+0

Вау, эта проблема намного сложнее, чем кажется на первый взгляд, на мой взгляд. Существует множество способов решить эту проблему, если вы готовы нарушить полную безопасность типов, но в противном случае ... ничего себе. – 2008-10-02 05:37:45

ответ

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. Его механизм прозрачен: вы получаете естественный синтаксис для вызывающего/пользователя и естественный синтаксис для собственного «возвращаемого состояния» функции; заявление.

  3. Это, вероятно, имеет нулевой накладные: На современных компиляторов, прокси-класс, с его хранением и функций, должны инлайн и оптимизировать ни к чему.

2

Моя философия не использует указатели функций raw-элемента. Я даже не знаю, как сделать то, что вы хотите, используя синтаксис raw pointer 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); } 
}; 

Эта проблема, безусловно, намного сложнее, чем кажется на первый взгляд

+0

Хех, я видел ваш более ранний ответ. Вероятно, это лучший компромисс; Я обсуждал это в IRC и пришел к выводу, что typedef, ссылаясь на себя, вероятно, является «слишком сложной» проблемой. – 2008-10-02 05:29:24

+0

Хотя, во внутренней boost :: function0, вам не нужно указывать тип возвращаемого значения и повторять эту процедуру? – 2008-10-02 05:30:46

+0

Может быть, я не сижу у компилятора – 2008-10-02 05:32:19

3

EDIT: njsf доказали меня неправильно. Тем не менее, вы можете обнаружить, что статическое кастинг проще поддерживать, поэтому я останусь здесь.

Там нет «правильного» статического типа , так как полный тип является рекурсивным:

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

Лучше всего использовать typedef void (StateMachine::*StateMethod)(); затем сделать уродливого state = (StateMethod)(this->*state)();

PS: boost::function требует явного возвращаемый тип, по крайней мере, из моего показания docs: boost::function0<ReturnType>

8

Использование только ЬурейеЕ:

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

};  
0

Я никогда не могу вспомнить ужасный C++ функция declspec, поэтому всякий раз, когда я должен узнать синтаксис, который описывает функцию-член, например, я просто индуцировать преднамеренную ошибку компилятора, которая обычно отображает правильный синтаксис для меня.

Так Дано:

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

Что синтаксис ЬурейеЕ stateA в? Понятия не имею .. поэтому давайте попробуем назначить ему что-то не связанного и посмотреть, что говорит составитель:

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.

Смежные вопросы