Cannot compile FSM sample code - c++

There is a nice state machine tutorial called UML Tutorial: Finite State Machines by Robert C. Martin. But I can't compile the sample code it provides. I got *FsmTest.cpp(46) : error C2664: 'SetState' : cannot convert parameter 1 from 'class UnlockedState *' to 'class TurnstileState '
Please, help. Thanks.
class Turnstile
{
public:
virtual void Lock();
virtual void Unlock();
virtual void Thankyou();
virtual void Alarm();
};
class TurnstileFSM;
class LockedState;
class UnlockedState;
class TurnstileState
{
public:
virtual void Coin(TurnstileFSM*) = 0;
virtual void Pass(TurnstileFSM*) = 0;
protected:
static LockedState lockedState;
static UnlockedState unlockedState;
};
class TurnstileFSM : public Turnstile
{
public:
void SetState(TurnstileState* s) {itsState = s;}
void Coin() {itsState->Coin(this);}
void Pass() {itsState->Pass(this);}
private:
TurnstileState *itsState;
};
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->SetState(&unlockedState);
t->Unlock();
}
virtual void Pass(TurnstileFSM* t)
{
t->Alarm();
}
};
class UnlockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->Thankyou();
}
virtual void Pass(TurnstileFSM* t)
{
t->SetState(&lockedState);
t->Lock();
}
};
LockedState TurnstileState::lockedState;
UnlockedState TurnstileState::unlockedState;

The problem is that when you try to call SetState() inside of LockedState::Coin(), the class UnlockedState is an incomplete type: it has been declared but not defined. In order to fix it, you'll need to move the definition of of Coin() to after that of UnlockedState:
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t);
...
};
class UnlockedState : public TurnstileState
{
...
};
void LockedState::Coin(TurnstileFSM* t)
{
...
}

Most likely this is because it does not know UnlockedState is a subclass of TurnstileState yet. Remove the function from inside the class to the end of the file:
class TurnstileFSM {
void SetState(TurnstileState* s);
};
void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}

In the example, the generated code should include the tscontext.h, and the TurnStyle class is derived from the context, which should be declared in *tscontext.h" as class TurnStyleContext.
In my case the generated code looks like this:
#include "tscontext.h" // the header file name for the context class"
// Forward Declarations
class TurnStyle;
//----------------------------------------------
// TurnStyleState: The base state class
//----------------------------------------------
class TurnStyleState
{
public:
virtual const char* StateName() const = 0;
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// State: Unlocked
//----------------------------------------------
class TurnStyleUnlockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Unlocked"; }
virtual void Pass( TurnStyle& );
virtual void Coin( TurnStyle& );
};
//----------------------------------------------
// State: Locked
//----------------------------------------------
class TurnStyleLockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Locked"; }
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// TurnStyle: The Finite State Machine class
//----------------------------------------------
class TurnStyle: public TurnStyleContext
{
public:
// Static State variables
static TurnStyleUnlockedState Unlocked;
static TurnStyleLockedState Locked;
TurnStyle(); // default Constructor
// Event functions
virtual void Coin() { itsState->Coin( *this ); }
virtual void Pass() { itsState->Pass( *this ); }
// State Accessor functions
void SetState( TurnStyleState& theState ) { itsState = &theState; }
TurnStyleState& GetState() const { return *itsState; }
const char* GetCurrentStateName() const { return itsState->StateName(); }
const char* GetVersion() const;
private:
TurnStyleState* itsState;
};
with the state machine defined this way:
Context TurnStyleContext // the name of the context class
FSMName TurnStyle // the name of the FSM to create
Initial Locked // the name of the initial state
// for C++ output
pragma Header tscontext.h" // the header file name for the context class, note the necessary "
{
Locked
{
Coin Unlocked Unlock
Pass Locked Alarm
}
Unlocked <BeforeUnlocked >AfterUnlocked
{
Coin Unlocked Thankyou
Pass Locked Lock
}
}
The context implements FSMError, Thankyou, Lock, Alarm, Unlock, BeforeUnlocked, AfterUnlocked

Related

Call a function inside an unknown class that extends a known class

As the title says I have the following "base" class that user can extend:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start();
virtual void EventHandler(SDL_Event event);
virtual void Update();
virtual void Draw();
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
My problem is I can't know what name, the user, choose for his classes so how I can call a known method (like Start or EventHandler) from my main class inside an unknown class?
An example of a class that is unknown to me but well-known to the user can be:
class SomeFunnyRandomName : public BaseScene
{
public:
void Start();
void Eventhandler(SDL_Event event);
void Update();
void Draw();
};
So form the main class I need to call Start() inside "SomeFunnyRandomName" without:
SomeFunnyRandomName sfrn = new SomeFunnyRandomName();
If you can include the code it will be very helpful (but not required).
You take a reference or pointer to BaseScene, and call the methods on that. The caller passes an instance of their derived class.
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene & scene) : scene(scene) {}
void doStuff() { scene.Start(); scene.Update(); }
/*... etc*/
};
int main() {
SomeFunnyRandomName scene;
UsesScene usesScene(scene);
usesScene.doStuff();
}

Is it possible to have a virtual type in C++?

I have a class MyClass (with several virtual functions) that performs operations on an object called MyType.
The class MyClassImpl inherits MyClass and implements the virtual functions, but I need to add additional members to MyType, but I don't want to modify the class MyType (instead I want to keep it generic).
Now, if I make a MyTypeImpl and inherit MyType, I can add members. But, how do I make the non virtual functions in MyClassImpl (inherited from MyClass) use the new MyTypeImpl?
The only way I can think is to make MyClass use MyTypeImpl but I want to avoid using the implementation in the generic class because I might use various different implementations.
Here is a simple example of what the classes might look like. Of course, the code will not compile because the methods and members added in MyTypeImpl and not MyType.
class MyType {
public:
void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
class MyTypeImpl : public MyType {
public:
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClassImpl : public MyClass{
public:
void print() {
mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_.increment();
mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_.decrement();
mytype_.decrement();
};
};
After seeing your example I see now that you just want to extend the functionality of that class without modifying the original class. If you need to add additional functions, but you don't want to change the type that is stored in MyClass there isn't any way I know of to make that happen without at least modifying MyType to include virtual functions for the functions you want to call.
You also need to make MyClass take a pointer to MyType so you can use polymorphism and make the calls resolve to the correct implementation:
Dynamic Polymorphism Solution:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
// To be implemented by implementation class
virtual void print() = 0;
// To be implemented by implementation class
virtual void decrement() = 0;
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << 42 << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClass {
public:
MyClass(MyType* mytype)
: mytype_(mytype)
{}
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType* mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_->increment();
};
};
class MyClassImpl : public MyClass{
public:
MyClassImpl(MyType* mytype)
: MyClass(mytype)
{}
void print() {
mytype_->print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_->increment();
mytype_->increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_->decrement();
mytype_->decrement();
};
};
int main()
{
MyType* mytype = new MyTypeImpl();
MyClass* myclass = new MyClassImpl(mytype);
// Prints "42"
myclass->print();
// Do other stuff with "myclass"
delete myclass;
delete mytype;
}
Note, I am only using a raw pointer in this example for increased clarity. It is highly recommended that you don't use new and delete and use smart pointers to manage the lifetime of your pointers instead.
Static Polymorphism Solution:
Not that the design of this solution is actually any better, but I think this is closer to what you are actually looking for because it doesn't require modifying the MyType class directly. Also the only modification needed for MyClass is to make it a template class:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << data_ << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;
};
template <typename T>
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
T mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
template <typename T>
class MyClassImpl : public MyClass<T> {
public:
void print() {
this->mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
this->mytype_.increment();
this->mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
this->mytype_.decrement();
this->mytype_.decrement();
};
};
int main()
{
// Use the template to get the correct implementation
MyClassImpl<MyTypeImpl> myclass;
myclass.alg();
myclass.print();
// Do other stuff with my class
}

C++ : function pointer and class members

I have a problem with the following piece of code that can't even compile.
The problem is on the line
class2_ = new Class2(myFunction);
In fact, I don't now how to reference myFunction, I have also tried class2_ = new Class2(&Class3::myFunction); but the compiler still complains :(
2 constraints:
The function myFunction can't be declared as static
This code will be used in a Arduino base project, I can't use boost::bind
Could you please help me ?
Thanks.
class Class2 {
typedef void(*MyFunction) (int what);
MyFunction fn_;
public:
Class2(MyFunction fn) : fn_(fn) {}
void invoke(int val) {
fn_(val);
}
};
class Class3 {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(myFunction);
class2_->invoke(12);
}
void myFunction(int what) {
// Do some work
}
};
void test2() {
Class3 instance3;
}
How about using an interface for that:
class ClassWithFunction {
public:
virtual void myFunction(int what) = 0;
}
class Class2 {
ClassWithFunction* fn_;
public:
Class2(MyFunction* fn) : fn_(fn) {}
void invoke(int val) {
fn_->myFunction(val);
}
};
class Class3 : ClassWithFunction {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(this);
class2_->invoke(12);
}
void myFunction(int what) {
// Do some work
}
};
You need to use pointer to member function.
class Class3;
class Class2 {
typedef void(Class3::*MyFunction) (int);
MyFunction fn_;
public:
Class2(MyFunction fn) : fn_(fn) {}
void invoke(Class3 *p, int val) {
(p->*fn_)(val);
}
};
class Class3 {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(&Class3::myFunction);
class2_->invoke(this, 12);
}
void myFunction(int what) {
// Do some work
}
};
If you want that Class2 accepts any callable object with signature void(int), then class template, function wrapper, lambda expression etc. will help.

Forward declaration of inherit class

The programm below is about polymorphism. It just changes the status of a door between open and closed. My problem is that i can't switch the status in my class "Open" to closed since the class "Close" is below my class "Open".
How can i forward declare the class "Close" that it will work properly? (since a normal forward declaration like 'class Close;' doesnt seem to work)
class Status;
class Door {
private:
Status* currentStatus;
public:
void setStatus(Status*);
void opendoor();
void closedoor();
};
class Status {
public:
virtual void opendoor(Door* s)=0;
virtual void closedoor(Door* s) = 0;
};
class Open : public Status {
public:
void opendoor(Door* s) {
return;
}
void closedoor(Door* s){
s->setStatus( new Close() ); //Error here
return;
}
};
class Close : public Status {
public:
void opendoor(Door* s) {
s->setStatus( new Open() );
return;
}
void closedoor(Door* s){
return;
}
};
void Door::opendoor() {
currentStatus->opendoor(this);
return;
}
void Door::closedoor(){
currentStatus->closedoor(this);
return;
}
void Door::setStatus(Status* x) {
delete currentStatus;
currentStatus = x;
return;
}
The easiest would be to separate the class from the implementation: first declare all the classes. Then only the implementation of the member functions.
class Status;
class Door {
...
};
class Status {
...
};
class Open : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
class Close : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
...
void Open::closedoor(Door* s){
s->setStatus( new Close() ); //no more error here
return;
}
Define the member function that needs the full definition of Close after the full implementation of Close. For example,
void Open::closedoor(Door* s)
should be defined outside your class, after class Close. That's because in the line
s->setStatus( new Close() )
the compiler needs to know the full definition of Close, as it tries to constructs an object of type Close.

c++ double dispatch observer notification

Here is the code I am currently troubleshooting:
void CTimer::notify()
{
std::vector<IObserver*>::iterator it;
for(it=observers.begin();it!=observers.end();++it)
{
ITimerNotification* notification = new CTimerNotification(now());
(*it)->readNotification(*notification);
}
}
class CTimerNotification : public ITimerNotification
{
public:
CTimerNotification(const timeval& t)
{
time = t;
}
protected:
timeval time;
private:
virtual ~CTimerNotification();
virtual void read(const IObserver& o) const
{
o.update(*this);
}
virtual const timeval& getTime() const
{
return time;
}
};
class IObserver
{
public:
virtual ~IObserver();
virtual void readNotification(const INotification&) const=0;
virtual void update(const INotification&) const=0;
};
class ITimerObserver : public IObserver
{
public:
virtual void update(const ITimerNotification&) const=0;
};
class TestObserver : public ITimerObserver
{
public:
virtual void readNotification(const INotification& n) const
{
n.read(*this);
}
virtual void update(const INotification& n) const
{
std::cout<<"???: TestObserver: update()!\n";
}
virtual void update(const ITimerNotification& n) const
{
std::cout<< n.getTime().tv_sec << "." << n.getTime().tv_usec <<": TestObserver: update()!\n";
}
};
So the code runs, CTimer::notify() gets called, which creates a TimerNotification and passes it to the observer via readNotification() which in turn calls the notification's read() method, which finally calls the observer's (hopefully) correct update() method.
The last step is what fails. It calls the update(INotification&) method instead of the desired update(ITimerNotification&) method.
What am I missing here for this attempted Double Dispatch pattern to work? It does not appear to be getting the correct type information to select the appropriate function call.
Thanks for any help!
CTimerNotification needs a read something like this
virtual void read(const IObserver& o) const {
ITimerObserver* to = dynamic_cast<ITimerObserver*>(&o);
if (to) {
to->update(*this);
} else {
o.update(*this);
}
}
and you need a using IObserver::update; in ITimerObserver.