将成员函数作为参数传递给另一个函数?

问题描述 投票:0回答:1

我正在尝试编写一个机器人以获取乐趣。我想添加一个自主循环,以便机器人可以遵循一组预设命令并自行驱动。问题是,机器人的每个子系统都是不同的类,我希望能够创建一个类似这样的函数:

DoFunctionForMe(start_time, end_time, function, start_arguments, end_arguments);

我想要

DoFunctionForMe
做的是在开始时间执行带有开始参数的函数,并在结束时间执行结束参数。

例如,我可以有以下内容,从时间 1 行驶到时间 8,并从时间 7 行驶到时间 9:

void Robot::AutoMainLoop(){
    DoFunctionForMe(1,8,Drive,{12,12},{0,0});
    DoFunctionForMe(7,9,Move,{1,0},{0,0});
}

这是我迄今为止的代码的近似值:

class Drivetrain{
    public:
        Drivetrain();

        void Drive(int forward, int left){
            drive(forward, left); // Drives the robot, more complex than this 
        }
}

class Mechanism{
    public:
        Mechanism();

        void Move(int up, int down){
            move(up, down); // Moves the arm, more complex than this
        }
}

class Robot{
    public:
        void DrivenMainLoop(); // Operated by a person

        void AutoMainLoop(); // Robot operates itself

    private:
        Drivetrain m_drivetrain{}; 

        Mechanism m_mechanism{};

}

void Robot::DrivenMainLoop(){
    m_drivetrain.Drive(2,12);

    m_mechanism.Move(1,0);

}

void Robot::AutoMainLoop(){
    // help
}

我有办法做到这一点吗?

我尝试过使用指向函数的指针,但我不太明白我在那里做什么,并且它给了我错误,例如

a pointer to a bound function may only be used to call the function

c++ function robotics
1个回答
0
投票

您的

Drive
Move
方法是单独类的非静态成员。您必须使用
std::bind()
+
std::function
或 lambda,以便
DoFunctionForMe()
在不知道它们来自哪些对象的情况下调用它们,例如:

class Drivetrain{
    public:
        Drivetrain();

        void Drive(int forward, int left){
            ...
        }
};

class Mechanism{
    public:
        Mechanism();

        void Move(int up, int down){
            ...
        }
};

class Robot{
    public:
        void DrivenMainLoop(); // Operated by a person

        void AutoMainLoop(); // Robot operates itself

    private:
        Drivetrain m_drivetrain{}; 

        Mechanism m_mechanism{};
};

...

void DoFunctionForMe(int start_time, int end_time, std::function<void(int,int)> the_function, int[] start_arguments, int[] end_arguments) {
    ...
    the_function(...);
    ...
}
/* or:
template<typename Callable>
void DoFunctionForMe(int start_time, int end_time, Callable the_function, int[] start_arguments, int[] end_arguments) {
    ...
    the_function(...);
    ...
}
*/

void Robot::AutoMainLoop(){
    using namespace std::placeholders;

    auto drive = std::bind(&Drivetrain::Drive, &m_drivetrain, _1, _2);
    DoFunctionForMe(1, 8, drive, ...);

    auto move = std::bind(&Mechanism::Move, &m_mechanism, _1, _2);
    DoFunctionForMe(7, 9, move, ...);

    // or:

    DoFunctionForMe(1, 8, [&](int arg1, int arg2){ m_drivetrain.Drive(arg1, arg2); }, ...);
    DoFunctionForMe(7, 9, [&](int arg1, int arg2){ m_mechanism.Move(arg1, arg2); }, ...);
}

或者,您可以使

Drivetrain
Mechanism
继承自一个公共基类,该基类定义了它们都重写的
virtual
方法,然后您可以使
DoFunctionForMe()
通过多态性对该基类进行操作,例如:

class Actionable{
    public:
        virtual void DoAction(int arg1, int arg2) = 0;
};

class Drivetrain : public Actionable {
    public:
        Drivetrain();

        void Drive(int forward, int left){
            ...
        }

        void DoAction(int arg1, int arg2) override{
            Drive(arg1, arg2);
        }
};

class Mechanism : public Actionable {
    public:
        Mechanism();

        void Move(int up, int down){
            ...
        }

        void DoAction(int arg1, int arg1) override{
            Move(arg1, arg2);
        }
};

class Robot{
    public:
        void DrivenMainLoop(); // Operated by a person

        void AutoMainLoop(); // Robot operates itself

    private:
        Drivetrain m_drivetrain{}; 

        Mechanism m_mechanism{};
};

...

...

void DoFunctionForMe(int start_time, int end_time, Actionable *actionable, int[] start_arguments, int[] end_arguments) {
    ...
    actionable->DoAction(...);
    ...
}

void Robot::AutoMainLoop(){
    DoFunctionForMe(1, 8, &m_drivetrain, ...);
    DoFunctionForMe(7, 9, &m_mechanism, ...);
}
© www.soinside.com 2019 - 2024. All rights reserved.