将状态机的状态作为参数传递给函数指针C++ OOP

Passing states of StateMachine as parameter to a function pointer C++ OOP

本文关键字:函数 指针 C++ OOP 参数传递 状态机 状态      更新时间:2023-10-16

我对C++中的函数指针概念相当陌生,所以我不知道如何正确编写我的问题。请耐心等待。

基本上,我正在尝试做的是创建一个 Button 对象,其构造函数接受函数指针作为其参数。 该函数指针指向将更改状态机状态的函数。

这是示例代码(它不起作用,并且不相关的位已被剥离(

按钮.h

#include "StateMachine.h"
class Button
{
private:   
    void (*m_onclickAction)();    //a data member
public:
    Button(void (*action)());
};

StateMachine.h(我没有写它,我只是在获得许可的情况下使用它。所以代码应该没有问题,我不想修改它(

#include <map>
template<class E, class T>
class StateMachine
{
public:
    typedef void (T::*CallbackOnInitialise)();
    typedef void (T::*CallbackOnExit)();
private:    
    T* m_pOwner;
    E m_currentState;
    // Maps to store function pointers to state functions.
    std::map<E, CallbackOnInitialise> m_statesOnInitialise;
    std::map<E, CallbackOnExit> m_statesOnExit;
public:
    StateMachine(T* pOwner, E emptyState)
    {
        m_currentState = emptyState;
        m_pOwner = pOwner;
    }
    void ChangeState(E statenext)
    {
        //do something to change the state
    }
};
这样

在我的主程序课上,我就可以做这样的事情

#include "Button.h"
#include "StateMachine.h"
//Code to instantiate an StateMachine object goes here
Button* aButton = new Button(aStateMachine->ChangeState(NEW_STATE));

问题是我想不出正确传递NEW_STATE的方法,这是在 Program 类中声明的枚举,因为函数指针不需要任何参数。我尝试过调整它,但没有成功。

关于我应该怎么做的任何建议?

你在这里有几个问题。首先,在您的版本中,您在创建Button实例时调用 ChangeState 成员函数。第二种是m_onclickAction是指向函数的指针,它与指向成员函数的指针不同。

为此,我建议您研究std::functionstd::bind

class Button
{
    std::function<void(int)> m_onclickAction;
public:
    Button(std::function<void(int)> action) { ... }
};

然后,您可以像这样创建按钮:

Button* aButton = new Button(
    std::bind(&StateMachine::ChangeState, aStateMachine, NEW_STATE));

对于回调,boost::bind(( 和 boost::function(( 是一个非常有用的工具。因此,您的 Button 类可能如下所示:

class Button
{
public:
    typedef boost::function<void()> Callback;
    Button( Callback clickAction );
private:   
    Callback m_onclickAction;    //a data member
};

将带有参数的状态机方法传递给的代码将是:

Button* aButton = new Button( boost::bind( &StateMachine::ChangeState, aStateMachine, NEW_STATE ) );

如果您使用 C++11,您可以将 boost::bind 替换为 std::bind 和 boost::function 替换为 std::function。

Tha 库有一个设计错误。

问题是函数指针

只是C++中的函数指针(不是闭包(,因此它没有任何上下文。

如果你想创建一个绘制蓝色圆

圈的按钮,你将需要一个全局函数,该函数将绘制一个不带参数的蓝色圆圈。

如果你想要另一个按钮来绘制一个黄色圆圈,你将需要另一个全局函数来绘制一个不带参数的黄色圆圈。

更具体地说,问题是库没有任何方法在按钮中存储所谓的"上下文",以便能够向代码传递用于绘制圆圈的颜色。

C++11 添加了一些东西,提醒了一些闭包(不是真的,因为生命周期问题在没有垃圾回收的情况下很难在任何语言中解决(,但它们不是裸函数指针。

如果不更改 Button 类,你想做的事情是不可能的,除非你使用一些糟糕的 hack,就像你在这里看到的那样,它试图使用裸函数指针在 C 中模拟std::bind