【问题标题】:Private member functors for a C++ classC++ 类的私有成员函子
【发布时间】:2013-05-19 05:34:54
【问题描述】:

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

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,从而将正文和要求放在一个单独的文件中,但这对于一个相当简单的任务来说感觉像是很多开销。有没有我不知道的好方法?

【问题讨论】:

  • 为什么不将它们作为简单的成员函数,并在将它们传递给调度程序时绑定它们所需的数据(通过std::bind 或只是一个简单的 lambda)?
  • 无关:请不要为 C++ 函数对象使用名称“函子”。我知道它被很多人使用;我要求每个人都避免它。这是一个误称。这个词在 CS 和数学中具有公认的含义,如果我们不将其用于完全不相关的事物,每个人都会变得更好。
  • @n.m.我知道范畴论中的函子是什么,但考虑到“函子”是 c++ 中最常用的术语,我将继续使用它。
  • @Xeo 我可以这样做,但我将不得不多次将每一个传递给调度程序,并且我不想多次给它相同的数据。它不是很干燥。
  • @kunkelwe:将绑定打包到它自己的函数中。 :P

标签: c++ class c++11 lambda functor


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2019-12-29
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 2020-03-22
    • 2021-08-29
    • 2013-05-23
    • 2011-07-30
    • 1970-01-01
    相关资源
    最近更新 更多