问题 问答题

【说明】 传输门是传输系统中的重要装置。传输门具有Open(打开)、Closed(关闭)、Opening (正在打开)、StayOpen(保持打开)和Closing(正在关闭)五种状态。触发传输门状态转换的事件有click、complete和timeout三种。事件与其相应的状态转换如下图所示。

下面的C++代码1与C++代码2分别用两种不同的设计思路对传输门进行状态模拟,请填补代码中的空缺。【C++代码1】 const int CLOSED=1; const int OPENING=2; const int OPEN=3; const int CLOSING=4; const int STAYOPEN=5; //定义状态变量,用不同整数表示不同状态 class Door { Private: int state; //传输门当前状态 void setState(int state){ this->state=state;} //设置当前状态 public: Door():state(CLOSED){}; void getState(){ //根据当前状态输出相应的字符串 switch(state){ case OPENING: cout<<"OPENING"<<endl; break; case CLOSED: cout<<"CLOSED"<<endl; break; case OPEN: cout<<"OPEN"<<endl;break; case CLOSING: cout<<"CLOSING"<<endl; break; case STAYOPEN:cout<<"STAYOPEN"<<endl; break; } }; void click() { //发生click事件时进行状态转换 if ( (1) ) setState(OPENING); else if ( (2) ) setState(CLOSING); else if ( (3) ) setState(STAYOPEN); } void timeout(){ //发生timeout事件时进行状态转换 if (state == OPEN) setState(CLOSING); } void complete(){ //发生complete事件时进行状态转换 if (state == OPENING) setState(OPEN); else if (state == CLOSING) setState(CLOSED); } }; int main(){ Door aDoor; aDoor.getState();aDoor.click(); aDoor.getState(); aDoor.complete();aDoor.getState(); aDoor.click(); aDoor.getState();aDoor.click(); aDoor.getState(); return 0; }【C++代码2】 class Door { public: DoorState *CLOSED,*OPENING,*OPEN,*CLOSING,*STAYOPEN,*state; Door(); virtual~Door(){……//释放申请的内存,此处代码省略); void setState(DoorState *state) { this->state = state;} void getState(){//此处代码省略,本方法输出状态字符串,//例如,当前状态为CLOSED时,输出字符串为“CLOSED” }; void click(); void timeout(); void complete(); }; Door::Door(){ CLOSED = new DoorClosed(this); OPENING = new DoorOpening(this); OPEN = new DoorOpen(this);CLOSING = new DoorClosing(this); STAYOPEN = new DoorStayOpen(this);state = CLOSED; } void Door :: click() { (4) ;) void Door :: timeout() { (5) ;) void Door :: complete() { (6) ;} class DoorState//定义一个抽象的状态,它是所有状态类的基类 { protected:Door *door; public: DoorState(Door *door) {this->door = door;} virtual~DoorState(void); virtual void click() {} virtual void complete() {} virtual void timeout() {} }; class DoorClosed :public DoorState{//定义一个基本的Closed状态 public: DoorClosed(Door *door) :DoorState(door) {} virtual ~ DoorClosed(){} void click(); }; void DoorClosed :: click() { (7) ;} //其他状态类的定义与实现代码省略 int main() { Door aDoor; aDoor.getState();aDoor.click();aDoor.getState();aDoor.complete(); aDoor.getState();aDoor.timeout();aDoor.getState();return 0; }

答案

参考答案:

解析:(1)state == CLOSED || state == CLOSING (2)state == OPENING || state == STAYOPEN (3)state == OPEN (4)state->click() (5)state->timeout() (6)state->complete() (7)door->setState(door->OPENING)

[分析]: 本题考查的是状态转换图的程序设计与实现。 空(1)、(2)和(3)需要根据状态转换图来填写,空(1)、(2)和(3)所在的方法为click,表示当发生click事件时应该发生什么状态转换。根据代码可知,发生click事件时,状态分别跳转到OPENING,CLOSING和STAYOPEN,则发生click前的状态由状态转换图可以得到,分别为CLOSED或CLOSING、STAYOPEN或OPENING以及OPEN。 代码2中空(4)、(5)和(6)考查当发生click、timeout以及complete事件的时候,状态应该如何迁移。类Door的state成员变量用于记录类Door所处的状态,而state变量的类型为DoorState *,DoorState中分别具有click、timeout和complete方法用来响应对应的事件,因此,空(4)、(5)和(6)分别为:state->click()、state->timeout()和 state->complete()。 空(7)主要考查门的当前状态为CLOSED时,发生click事件时状态的迁移。根据状态图可知,CLOSED状态的在click事件下将迁移到OPENING,因此,此处应该将传输门状态设置为OPENING,DoorState变量存储了当前其存储的传输门的实例,因此,可直接调用其方法setState来设置状态,由于传输门状态采用类的实例变量表示,所以此处应该填写door->setState(door->OPENING)。 代码1和代码2的区别是:代码2将状态间的转换规则封装到具体的类中,当状态转换图的转换规则发生变化时,只需更改部分对应类中的状态迁移规则,而代码1中的迁移规则散落在程序中,维护起来较为困难。

单项选择题
问答题