状态机的实现!请各位高手帮忙!

米克贝瑞 2006-09-08 09:53:52
要实现一个状态机类,有事件触发的时候,想通过查状态表去执行动作函数,实现状态的迁移。大概的代码如下:
#define state1
#define state1
#define state1

#define event1
#define event2
#define event3

Class FSM
{
public :
run(event) //提供给外部调用的函数,执行状态机
private:
action1(); //动作函数
action1();
action1();
private:
statetable //状态表

}
状态表的存储结构应该是下面这样:
statetable=
{{state1(初始状态),event1(事件),action1(动作函数指针),state2(目标状态)},
{state2(初始状态),event2(事件),action2(动作函数指针),state3(目标状态)},
{state3(初始状态),event3(事件),action3(动作函数指针),state1(目标状态)},
}

上面是一些伪代码。实现过程中我遇到的问题是:
1:statetable应该用一个什么数据格式去存储?怎么实现?
2:函数指针怎么去存储和调用?因为这里是类的成员函数,对与这样的指针函数不知道怎么去处理。

请各位高手帮忙了!谢谢!
...全文
411 19 打赏 收藏 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
matchboy 2007-03-19
  • 打赏
  • 举报
回复
mark
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
OK了.通过了!再次感谢小西瓜的支持!
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
好!!万分感谢!!我先测试一下!
hdqqq 2006-09-08
  • 打赏
  • 举报
回复


你把
a.*(statetable[0].action_handle)(10,20);
改为

(a.*(statetable[0].action_handle))(10,20);

不好意思,少了个括号,优先级不一样.

我的测试代码,可以运行

struct state_unit
{
int b_state;
int event;
void (state_machine::* handle)();
int target;
};


state_unit s_table[] = {
{0,1, &state_machine::action1,1},
{1,1, &state_machine::action2,2},
{2,1, &state_machine::action3,0},
};

void run()
{
state_machine lma;
int i,j;
int cur_state = 0;
for (i = 0; i < 100; i++) {
for (j = 0; j < 3; j++) {
if (cur_state == s_table[j].b_state) {
(lma.*s_table[j].handle)();
cur_state = s_table[j].target;
break;
}
}
}
}
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
53行就是
a.*(statetable[0].action_handle)(10,20);
的那行
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
run()
{
FSM a;
a.*(statetable[0].action_handle)(10,20);
}

这样写应该是你的意思吧?但是编译报错:
fsm.cpp(53) : error C2064: term does not evaluate to a function
hdqqq 2006-09-08
  • 打赏
  • 举报
回复
你把run 中的代码贴上来看看
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
唉,惭愧啊.这样的写法我怎么也编译不过.

小西瓜你编译能通过吗?
hdqqq 2006-09-08
  • 打赏
  • 举报
回复
我的意思是,类成员函数,是不能单独运行的, 在执行这个成员函数之前,需要先把这个成员函数依附于这个类的某个实例或者 某个 指针, 然后用 .* 或者 ->* 去调用函数.

就是说, 在run 的实现中
需要有一个FSM 的实例 (用.*) 或者 指针变量也可以 (用->*)

然后调用
a.*(statestable[i].action_handle)();





hdqqq 2006-09-08
  • 打赏
  • 举报
回复
.* 用于 类实例 的成员函数
->* 用于 类指针 的成员函数
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
小西瓜,很奇怪,你这样写:
如果class_name 有某个实例

class_name lclass;
void (class_name::* lcall)() = statetable[i].actionhandle;
lclass.*lcall();

class_name *pclass;
pclass->*lcall();

之所以定义一个lcall 是为了把 actionhandle 复制一下,
你也可以试试
lclass.*(statetable[i].actionhandle)();
看看是否可以.


好象也是不行的哦?我这边编译都通不过.
baojian88888 2006-09-08
  • 打赏
  • 举报
回复
看看《设计模式》之state(状态机)
hdqqq 2006-09-08
  • 打赏
  • 举报
回复
如果是类成员函数的话,在运行的时候需要有个类的实例, 然后使用 .* 和->* 操作符去绑定 就可以了.
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
小西瓜厉害!!

现在问题是action()是FSM的成员函数,那么
state_unit{
int b_state; //初始状态
int event; //事件
void (* action_handle)(); //函数指针
int targte_state; //目标状态
}

这个结构里面函数指针这里应该怎么去定义呢?
我是这样子写的:
{
int b_state; //初始状态
int event; //事件
int (FSM::* action_handle)(int,int); //函数指针
int targte_state; //目标状态
}
编译可以通过;


statetable[0].action_handle(10,20);
这样调用执行的时候出错:(


hdqqq 2006-09-08
  • 打赏
  • 举报
回复
如果是类成员的话,把结构改一下
state_unit{
int b_state; //初始状态
int event; //事件
void (class_name::* action_handle)(); //函数指针
int targte_state; //目标状态
}

//初始化状态表
//可以直接在代码中定义
state_unit statetable[] =
{ {0, 0, &class_name::action1, 1},
{0, 1, &class_name::action2, 2},
}

运行时候
如果class_name 有某个实例

class_name lclass;
void (class_name::* lcall)() = statetable[i].actionhandle;
lclass.*lcall();

class_name *pclass;
pclass->*lcall();

之所以定义一个lcall 是为了把 actionhandle 复制一下,
你也可以试试
lclass.*(statetable[i].actionhandle)();
看看是否可以.


hdqqq 2006-09-08
  • 打赏
  • 举报
回复
run(event) // 的实现
{
int statesize = sizeof(statetalbe) / sizeof(state_unit);
int i;
for (i = 0; i < statesize; i++) {
if (cur_state == statetable[i].b_state && event == statetable[i].event) {
statetable[i].action_handle();
cur_state = statetable[i].target_state;
break; //cur_state 为状态机当前状态
}
}
}
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
谢谢小西瓜的解答!问题是action1()是类的成员函数,怎么去定义和调用呢?

如果是不是类的成员函数应该很好处理的.
hdqqq 2006-09-08
  • 打赏
  • 举报
回复
statetable 可以用数组的方式实现, 单个的状态处理定义为一个结构

state_unit{
int b_state; //初始状态
int event; //事件
void (* action_handle)(); //函数指针
int targte_state; //目标状态
}

//初始化状态表
//可以直接在代码中定义
state_unit statetable[] =
{ {0, 0, action1, 1},
{0, 1, action2, 2},
}

然后在run 中查询状态表并进行相关操作
这种方式要求, action 的函数格式是相同的,如果你不熟悉 函数指针的话, 看一下相关资料
米克贝瑞 2006-09-08
  • 打赏
  • 举报
回复
up

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧