0

I'm quite a newbie using C ++. I am trying to implement in C ++, the state machine described in this link for C language: https://barrgroup.com/Embedded-Systems/How-To/Coding-State-Machines.

I have created an Fsm class, which implements the behavior of the state machine, and a Machine class, whose methods will be the states.

The code works, but it generates a warning (-Wpmf-conversions) when I try to save the memory address of a Machine method, in State state__

class Fsm
{
public:
    typedef void (*State)();
private:
    State state__;
public:
    Fsm(State state);
    void dispatch();
}; 

Fsm::Fsm(State state)
{
    state__ = state ;
} //Fsm

void Fsm::dispatch()
{
    (*state__)() ;
}



class Machine : public Fsm
{
public:
    Machine() : Fsm((State)&Machine::initial) {}       // ctor
}; 

I'm using an Atmega2560, with AVR-GCC compiler.

  • 1
    For what line of code is the warning generated? Also, why does your Fsm class have two "public" access specifiers. And why type-def (*State)() as void? It could be that I'm forgetting my C++, but I don't see what you're trying to do here. – Paul Nov 5 '19 at 22:56
  • @Paul typedef void (*State)(); is a typedef for a function pointer to a function with no parameters and a void return type. It is perfectly normal to have multiple public, protected or private sections in a class. – Majenko Nov 6 '19 at 10:45
  • A "PMF" is a Pointer to a Member Function. In C++ this is not allowed. – Majenko Nov 6 '19 at 10:49
2

A pointer to a member function is not allowed in C++. GCC can allow it, but moans at you because it's non-standard.

In C++ the normal way of dealing with the kind of thing you want is through class inheritance.

Typically you would create your base Fsm class that implements the basic functionality of your state machine control, then overlay over the top of that (create a new class that inherits the Fsm class) another class that implements your specific machine functionality. You can declare functions in your base Fsm class that are pure virtual - that is, they exist, but have no body. It's then the job of the child class to actually implement that functionality. The parent Fsm class then knows about those functions and can call them.

So you would have something like:

class Fsm {
    public:
        void dispatch();
    protected:
        virtual void initial() = 0;
}; 

void Fsm::dispatch() {
    initial() ;
}



class Machine : public Fsm {
    protected:
        void initial() {
             Serial.println("Here");
        }
}; 

Machine mach;

mach.dispatch(); // --> "Here"

Fsm knows about initial(), but the function hasn't been further defined. Machine implements initial(). You then create an instance of Machine which contains everything needed. Calling dispatch() runs the function in the Fsm parent class which then calls initial() in the child Machine class.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.