关于在 ROS2 教程中使用 std::bind 的问题

Question regarding the use of std::bind in ROS2 tutorial

我是 C++ 的新手,我对 std::bind 的实践有疑问。以下片段是从 tutorial on the ROS2 website 复制而来的。该代码创建一个 class,其中 timer_ 字段托管一个使用 create_wall_timer() 创建的计时器。 creates_wall_timer() 接受类型为 CallbackT && 的回调对象。在class的构造函数中,为什么作者将std::bind(...)的结果作为回调传递给create_timer(),而不是直接指向timer_callback方法的指针或引用?

很抱歉问题很长。我不太擅长问这些问题。希望我没有遗漏太多您需要的信息。

#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the timer. */

class MinimalPublisher : public rclcpp::Node
{
  public:
    MinimalPublisher()
    : Node("minimal_publisher"), count_(0)
    {
      publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
      timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    void timer_callback()
    {
      auto message = std_msgs::msg::String();
      message.data = "Hello, world! " + std::to_string(count_++);
      RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
      publisher_->publish(message);
    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;
};

您不能单独将指针传递给成员函数(除非该函数被声明为 static),因为它需要调用 [正确类型] 对象的实例。

std::bind 将指向对象的指针(在本例中为 this)绑定到成员函数指针(&MinimalPublisher::timer_callback),以便在调用该函数时,有可用的所需/所需对象的实例。

要从另一个(更简单的)角度来看这个问题,请考虑如果您这样写会发生什么:

MinimalPublisher::timer_callback ();

如果 MinimalPublisher::timer_callback 不是 static 函数编译器会报错,因为非静态函数只能通过 [指向 a] MinimalPublisher 对象的指针调用,所以类似于:

my_minimal_publisher_object.MinimalPublisher::timer_callback ();

或:

my_minimal_publisher_object_pointer->MinimalPublisher::timer_callback ();

您可能想在 favourite online compiler 中试验一下。

顺便说一句,std::bind 已在很大程度上被 capturing lambdas these days. So, in order to capture the required object instance (and taking my original example over at Wandbox as a starting point), you might do 取代:

#include <functional>

struct MyStruct
{
    void foo ();
};

int main()
{
    MyStruct s;
    std::function <void ()> f = [&s] { s.foo (); };
    // Do things with f
}