简体   繁体   中英

c++ iterating over member functions

I have a bit of a design problem:

I have a class describing a Robot; It can move to different directions, move a camera to different views etc. It looks something like this:

class Robot {
    private:
        ...

    public:
        void move_right();
        void move_left();
        void switch_camera()
        void raise_camera()
}

I want to add another method which performs a series of events. Thing is, I need able to abort the events midway.

I do want to clarify that the robot is running on a micro controller and not on a standard OS - so I can't really send a signal to the process or anything.

My first idea was to store the event functions in an array and iterate over it:

#typedef void(robo_event *)(void)

robo_event next_event;
robo_event *event_sequence;

Robot() {
    this->next_event = nullptr;

}


void perform_event_series() {
    for(this->next_event = *event_sequence; this->next_event != nullptr; this->next_event+=sizeof(robo_event)) {
        this->next_event();
    }
}

void abort_event_series() {
    this->next_event = nullptr;
}

Thing is, the c++ standard forbids storing addresses of member functions, so this is starting to get awkward. I can make the functions static, but I do need to use them quite frequently and that would still be awkward. I want to be able to change to event sequence without too much work if changes are yet to come, so I thought that saving those on some sort of array / vector would be the best.

Any help with c++ member function syntax / better ideas on how to approach this problem would be much appreciated.

Thing is, the c++ standard forbids storing addresses of member functions

C++ most certainly allows you to store pointers to member functions (and variables), but the syntax is a bit different to accommodate the this pointer type, virtual functions, inheritance, etc.

class Example
{
public:
    double foo(int x) { return x * 1.5; }
};
int main() {
    double (Example::* member_function_ptr)(int);
    member_function_ptr = &Example::foo;

    Example example;
    std::cout << (example.*member_function_ptr)(2) << std::endl;
}

If all your functions are for the same class, same return type, same arguments, etc. then you can make a table of them easy enough.

Pointers to functions are of different types to pointers to members.

You need void(Robot::*)(void) not void(*)(void) .

class Robot {
private:
    typedef void(Robot::*robot_event)(void)

    robo_event next_event;
    robo_event *event_sequence;

    Robot() {
        next_event = nullptr;

    } 

    void perform_event_series() {
        for(next_event = *event_sequence; next_event != nullptr; ++next_event) {
            (this->*next_event)();
        }
    }

    void abort_event_series() {
        next_event = nullptr;
    }

public:
    void move_right();
    void move_left();
    void switch_camera()
    void raise_camera()

}

Storing pointers to member functions is perfectly allowable in c++:

#include <vector>

class Robot {
    private:

    public:
        void move_right();
        void move_left();
        void switch_camera();
        void raise_camera();
};

struct Action
{
    Action(void (Robot::*what)(void))
    : what(what)
    {}

    void perform(Robot& who) const
    {
        (who.*what)();
    }

    void (Robot::*what)(void);
};

bool should_abort();

void perform_actions(Robot& who, std::vector<Action> const& actions)
{
    for (auto&& action : actions)
    {
        if (should_abort()) break;
        action.perform(who);
    }
}

int main()
{

    std::vector<Action> actions {
        &Robot::move_right,
        &Robot::raise_camera,
        &Robot::switch_camera,
        &Robot::move_left
    };

    Robot r;
    perform_actions(r, actions);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM