c++类的私有成员函子

Private member functors for a C++ class

本文关键字:成员 c++      更新时间:2023-10-16

我正在编写一个类,其中我希望有一些成员方法,这些方法有一些与它们相关的数据,特别是它们需要使用机器人的哪些机械系统。我想我可以把它们写成函子,就像这样(这不是我的实际代码):

class MyRobot : public Robot {
public:
  MyRobot();
  void runRobot();
private:
  Command do_something_,
          do_another_thing_;
}

然后在构造函数中用lambda初始化do_something_,如:

do_something_( [] {
  do_first_thing();
  do_second_thing();
} );

然后告诉do_something_它有什么要求:

do_something_.requires( system_a );
do_something_.requires( system_b );

runRobot()中,我会告诉机器人的调度程序执行以下命令:

void MyRobot::runRobot() {
  scheduler.add(do_something_);
  scheduler.add(do_another_thing_);
}

但是我已经意识到,随着命令数量的增长,MyRobot的构造函数将变得越来越难以管理,因为每个命令都将在那里定义其主体。我可以为每个命令创建一个相应的私有方法,并用函数指针而不是lambda来初始化它们,但这看起来更复杂。我还可以为每个特定的命令子类化Command,从而将每个命令的主体和需求放在一个单独的文件中,但是对于一个相当简单的任务来说,这感觉开销很大。有没有我不知道的好办法?

您可以定义Command类,以获取std::function和初始化列表中的"需求"。然后,您可以使do_somethingdo_another_thing成为自己的私有成员函数,而不必在构造函数中定义它们的主体,而不是使用lambdas。最后,在构造函数中,您可以通过将私有成员函数与当前MyRobot实例的this指针绑定来构造Command实例,同时还为它们提供一个需求列表。Command对象应该能够修改MyRobot实例的私有状态。下面是一个例子。另外,请参见示例输出。

#include <functional>
#include <iostream>
#include <vector>
enum System { SYS_A, SYS_B, SYS_C };
class Command {
public:
  typedef std::function<void()> FuncType;
  Command(FuncType func, std::initializer_list<System> requirements)
  :func_(func), requirements_(requirements) { }
  void operator()() {
    std::cout << "Executing Command:" << std::endl;
    for ( System s : requirements_ )
      std::cout << "   REQUIRES " << static_cast<int>(s) << std::endl;
    func_();
  }
private:
  FuncType            func_;
  std::vector<System> requirements_;
};
class Scheduler {
public:
  void add(Command c) {
    c();
  }
};
class Robot {
public:
  Robot()
  :do_something_    (std::bind(&Robot::do_something, this),     {SYS_A, SYS_B}),
   do_another_thing_(std::bind(&Robot::do_another_thing, this), {SYS_A, SYS_C}) { }
  void runRobot() {
    s_.add(do_something_);
    s_.add(do_another_thing_);
  }
private:
  void do_first_thing()  { std::cout << "   FIRST THING!" << std::endl;  }
  void do_second_thing() { std::cout << "   SECOND THING!" << std::endl; }
  void do_third_thing()  { std::cout << "   THIRD THING!" << std::endl;  }
  void do_something()     { do_first_thing(); do_second_thing(); }
  void do_another_thing() { do_first_thing(); do_third_thing();  }
  Command   do_something_;
  Command   do_another_thing_;
  Scheduler s_;
};
int main(int, char**) {
  Robot().runRobot();
}