为什么我们需要在std::bind()中指定对象来将其描述为函子?

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

我开始使用 ROS 并遇到了以下订阅者代码:-

#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node
{
public:
  MinimalSubscriber()
  : Node("minimal_subscriber")
  {
    subscription_ = this->create_subscription<std_msgs::msg::String>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
  }

private:
  void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
  {
    RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
  }
  rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}

我的困惑特别在于语法

subscription_ = this->create_subscription<std_msgs::msg::String>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));

根据我的理解,这是一个ROS节点,用于从名为“topic”的主题中订阅字符串类型的消息,并在有新消息时执行 topic_callback() 。来自一个非常原始的背景,我想问为什么我们甚至需要使用 bind() 函数?我们不能简单地传递 topic_callback 函数或指向该函数的指针作为参数(可能像 Python)吗?

为什么我们需要指定“this”?当我们引用 topic_callback 时,只有存在一个其成员函数为 topic_callback 的 MinimalSubscriber 对象才有意义,因此再次指定它似乎是多余的。与 _1 相同,仅传递 1 个参数,即 String。根据我的说法,可以传递 this->topic_callback 而不是绑定。

我可能在几个方面都错了。我确实看过这个优秀的答案:- std::bind(),但无法完全掌握。

c++ bind ros
1个回答
0
投票

这个问题不是 ROS 特有的。假设您有一个函数接受回调,返回

void
并接受 1
std::string
参数:

void foo(std::function<void(std::string)> callback) {
    if (callback) {
        callback("foo");
    }
}

如果你有一个自由函数

void freeFun(std::string)
,你可以直接传递它
foo(freeFun);
,但是如果你有一个类或结构:

struct Foo {
    void bar(std::string str) {
        std::cout << "bar str = " << str << "\n";
    }
    static void baz(std::string str) {
        std::cout << "baz str = " << str << "\n";
    }
    void registerCallback();
};

那么你不能简单地使用

bar
作为参数,因为
bar
需要调用
Foo
类型的对象。所以:

int main() {
    using namespace std::placeholders;
    // foo(&Foo::bar);  // nope
    foo(&Foo::baz); // ok, because static method doesn't need associated object
    Foo myFoo;
    foo(std::bind(&Foo::bar, &myFoo, _1));  // ok, but rarely used for practical reasons
}

void Foo::registerCallback() {
    foo(std::bind(&Foo::bar, this, _1));  // ok, typical use-case
}

std::bind
将(非正式地)具有签名
bar
的函数
void bar(Foo*, std::string)
转换为内部保存“绑定”参数的对象,并且可以像具有签名
void f(std::string)
的函数一样进行调用。

© www.soinside.com 2019 - 2024. All rights reserved.