关于在 ROS2 教程中使用 std::bind 的问题
Posted
技术标签:
【中文标题】关于在 ROS2 教程中使用 std::bind 的问题【英文标题】:Question regarding the use of std::bind in ROS2 tutorial 【发布时间】:2021-10-16 23:05:22 【问题描述】:我对 C++ 相当陌生,我对 std::bind 的做法有疑问。下面的 sn-p 就是从这个tutorial on the ROS2 website 复制过来的。该代码创建了一个类,其中 timer_ 字段承载了一个使用create_wall_timer()
创建的计时器。 creates_wall_timer()
接受 CallbackT &&
类型的回调对象。在类的构造函数中,为什么作者将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_;
;
【问题讨论】:
我们需要create_wall_timer
的声明。但很可能create_wall_timer
接受一个没有参数的函数对象,而一个成员方法有一个隐藏的this
参数,这就是使用bind 的原因。
【参考方案1】:
您不能单独传递指向成员函数的指针(除非该函数声明为 static
),因为它需要调用 [正确类型] 对象的实例。
std::bind
将一个指向对象的指针(在本例中为this
)绑定到成员函数指针(&MinimalPublisher::timer_callback
),以便在调用该函数时,有一个所需的实例/所需的对象可用。
要从另一个(更简单)的角度来看待这个问题,考虑一下如果你这样写会发生什么:
MinimalPublisher::timer_callback ();
如果 MinimalPublisher::timer_callback
不是 static
函数,编译器会报错,因为只能通过 [pointer to a] MinimalPublisher
对象调用非静态函数,因此类似于:
my_minimal_publisher_object.MinimalPublisher::timer_callback ();
或:
my_minimal_publisher_object_pointer->MinimalPublisher::timer_callback ();
您可能想在您的favourite online compiler 中进行此实验。
顺便说一句,std::bind
在很大程度上已被 capturing lambdas 取代。因此,为了捕获所需的对象实例(并以我在 Wandbox 的原始示例为起点),you might do:
#include <functional>
struct MyStruct
void foo ();
;
int main()
MyStruct s;
std::function <void ()> f = [&s] s.foo (); ;
// Do things with f
【讨论】:
这是否意味着一个类中的所有非静态函数在技术上都有一个“this”参数?根据我在 std::bind 上阅读的内容,它使用用户提供的参数填充函数。 是的,正是如此。没有this
指针,没有交易。 std::bind
所做的是将成员函数指针和指向对象的指针包装成 std::function
,以便在调用函数时用作 this
。如果成员函数签名需要它们,您还可以指定更多参数。 'this
必须是 std::bind
的第一个参数,并且任何其他参数必须跟随(按适当的顺序)。以上是关于关于在 ROS2 教程中使用 std::bind 的问题的主要内容,如果未能解决你的问题,请参考以下文章
std::bind 有多少个参数(VC 11 只支持 4 个)
ROS2初学者教程(Dashing和Eloquent)Windows