c ++ перебирает функции-члены - PullRequest
0 голосов
/ 10 октября 2018

У меня небольшая проблема с дизайном:

У меня есть класс, описывающий робота;Он может перемещаться в разные стороны, перемещать камеру в разные виды и т. Д. Это выглядит примерно так:

class Robot {
    private:
        ...

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

Я хочу добавить еще один метод, который выполняет серию событий.Дело в том, что мне нужно прервать события на полпути.

Я хочу уточнить, что робот работает на микроконтроллере, а не на стандартной ОС - поэтому я не могу отправить сигнал наили что-то в этом роде.

Моей первой идеей было сохранить функции событий в массиве и выполнить итерации по ним:

#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;
}

Дело в том, что стандарт c ++ запрещает хранить адреса функций-членов, поэтомуэто начинает становиться неловким.Я могу сделать функции статичными, но мне нужно использовать их довольно часто, и это все равно будет неудобно.Я хочу иметь возможность переходить на последовательность событий без особой работы, если изменения еще не наступили, поэтому я подумал, что лучше всего сохранить их в каком-либо массиве / векторе.

Любая помощь с членом c ++Синтаксис функции / лучшие идеи о том, как подойти к этой проблеме, будет высоко ценится.

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

Дело в том, что стандарт c ++ запрещает хранить адреса функций-членов

C ++, безусловно, позволяет хранить указатели на функции-члены (и переменные), но синтаксис немного отличаетсядля размещения this типа указателя, virtual функций, наследования и т. д.

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;
}

Если все ваши функции для одного класса, того же типа возврата, одинаковых аргументов и т. д., то вы можете сделатьтаблица из них достаточно проста.

0 голосов
/ 10 октября 2018

Хранение указателей на функции-члены вполне допустимо в 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);

}
0 голосов
/ 10 октября 2018

Указатели на функции относятся к указателям на элементы разного типа.

Вам нужно void(Robot::*)(void), а не 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()

}
...