У меня 2 класса. Я хочу передать this
из конструктора одного класса в качестве параметра в конструктор другого класса.
Я знаю, что ошибка произошла из-за того, что функция Shared_from_this() вызывается до того, как объект IkArm (this) будет полностью создан. Но я не могу найти способ передать узел второму классу после выполнения первого класса. Также я рассмотрел этот вопрос, но соотношение используемых там классов другое.
Ниже приведен код:
#include "rclcpp/rclcpp.hpp"
class IkSolver
{
public:
IkSolver(std::shared_ptr<rclcpp::Node> node) : node_(node)
{
RCLCPP_INFO(node_->get_logger(), "2nd Constructor");
}
private:
std::shared_ptr<rclcpp::Node> node_;
};
class IkArm : public rclcpp::Node
{
public:
IkArm() : Node("IkNode")
{
RCLCPP_INFO(this->get_logger(), "1st Constructor");
obj1_ = std::make_shared<IkSolver>(shared_from_this());
RCLCPP_INFO(this->get_logger(), "Back To 1st Constructor");
}
private:
std::shared_ptr<IkSolver> obj1_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<IkArm>());
rclcpp::shutdown();
return 0;
}
Я получаю следующую ошибку:
[INFO] [1720452645.004303274] [IkNode]: 1st Constructor
terminate called after throwing an instance of 'std::bad_weak_ptr'
what(): bad_weak_ptr
[ros2run]: Aborted
РЕДАКТИРОВАТЬ_1: После внесения изменений, предложенных @Ahmed AEK, возникает следующая ошибка:
error: could not convert ‘std::enable_shared_from_this<_Tp>::shared_from_this() [with _Tp = rclcpp::Node]()’ from ‘shared_ptr<rclcpp::Node>’ to ‘shared_ptr<IkArm>’
32 | return shared_from_this();
| ~~~~~~~~~~~~~~~~^~
| |
| shared_ptr<rclcpp::Node>
Обновленный код:
#include "rclcpp/rclcpp.hpp"
class IkSolver
{
public:
IkSolver(std::shared_ptr<rclcpp::Node> node) : node_(node)
{
RCLCPP_INFO(node_->get_logger(), "2nd Constructor");
}
private:
std::shared_ptr<rclcpp::Node> node_;
};
class IkArm : public rclcpp::Node
{
public:
IkArm() : Node("IkNode")
{
RCLCPP_INFO(this->get_logger(), "1st Constructor");
RCLCPP_INFO(this->get_logger(), "Back To 1st Constructor");
}
std::shared_ptr<IkArm> init()
{
obj1_ = std::make_shared<IkSolver>(shared_from_this());
return shared_from_this();
}
private:
std::shared_ptr<IkSolver> obj1_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<IkArm>()->init());
rclcpp::shutdown();
return 0;
}
Несколько не связано с рассматриваемым вопросом, но учтите, что если вы не предпримете дополнительные шаги для предотвращения этого (которые не показаны), ваш текущий код приведет к утечке памяти, поскольку IkArm
владеет IkSolver
, который, в свою очередь, владеет IkArm
. Ни один из счетчиков ссылок shared_ptr
никогда не достигнет 0 (и, следовательно, ни один объект никогда не будет удален), пока у вас есть этот цикл в вашем графе владения. std::weak_ptr
может помочь в решении этой проблемы.
Вы не можете вызвать shared_from_this
из конструктора, вы можете вызывать shared_from_this
только для объектов, которые уже привязаны к shared_ptr
, тогда как std::make_shared
привязывает объект к shared_ptr
после того, как его конструктор завершен.
из std::enable_shared_from_this
Разрешено вызыватьshared_from_this только на ранее опубликованном объект, то есть объект, управляемый std::shared_ptr. В противном случае, std::bad_weak_ptr выбрасывается (конструкторомshared_ptr из созданный по умолчанию слабый-это).
вам нужно поместить конструкцию члена в другую функцию-член, которую вы вызываете вне конструктора.
rclcpp::spin(std::make_shared<IkArm>()->init());
// init implemenation
std::shared_ptr<rclcpp::Node> IkArm::init()
{
obj1_ = std::make_shared<IkSolver>(shared_from_this());
return shared_from_this();
}
Также обратите внимание, что у вас есть циклическая ссылка , внутри члена следует хранить только weak_ptr
, а не shared_ptr
, иначе ни один из двух объектов не будет удален.
Спасибо за ответ. Но я получаю еще одну ошибку. Обновил вопрос.
@Pratham, просто вместо этого введите возвращаемый тип std::shared_ptr<rclcpp::Node>
.
Спасибо. Проблема решена. Для информации: работали ли вы ранее с библиотекой rclcpp (связанной с Robotics ROS2)?
Вы просто не можете использовать
shared_from_this
внутри конструктора. Обычно я думаю о том, как изменить API, обычно с помощью фабричной функции для создания объекта, а затем что-то сделать сshared_ptr
, или путем адаптации логики и «кто что делает» для размещенияshared_from_this
.