关于在 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
}
我是 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
}