在构造函数中使用关键字“this”时定义复制构造函数

Posted

技术标签:

【中文标题】在构造函数中使用关键字“this”时定义复制构造函数【英文标题】:Define copy constructor when keyword "this" is used inside constructor 【发布时间】:2019-02-01 14:53:23 【问题描述】:

我在定义我的类TextListener 的复制构造函数时遇到了困难。 TextListener 类使用 this 关键字绑定方法 callback。请看下面的完整代码:

#include <iostream>
#include <ros/ros.h>
#include <std_msgs/String.h>

class TextListener 
 private:
  std::string _text;
  ros::Subscriber _subscriber;

 public:
  TextListener() 
    std::cout << "[" << this << "] deafult constructor called" << std::endl;
  

  TextListener(const TextListener &other)
      : _subscriber(other._subscriber), _text(other._text) 
    std::cout << "[" << this << "] copy constructor called" << std::endl;
  

  TextListener &operator=(const TextListener &other) 
    std::cout << "[" << this << "] copy assignment called" << std::endl;
    _subscriber = other._subscriber;
    _text = other._text;
    return *this;
  

  TextListener(ros::NodeHandle &nh, const std::string &topicName) 
    std::cout << "[" << this << "] constructor called" << std::endl;
    _subscriber = nh.subscribe(topicName, 1, &TextListener::callback, this);
  

  void callback(const std_msgs::String::ConstPtr &msg)  _text = msg->data; 

  std::string &getText()  return _text; 

  ~TextListener() 
    std::cout << "[" << this << "] destructor called" << std::endl;
  
;

为了测试上面的类,我创建了它的一个实例,它可以正常工作。但是,当我创建一个新实例并将这个实例分配给新实例时,新实例不起作用。下面是代码sn-p:

int main(int argc, char **argv) 
  ros::init(argc, argv, "tet_listener");

  ros::NodeHandle nh;
  std::string topicName = "chatter";
  TextListener listener(nh, topicName);
  TextListener copyListener = listener;

  ros::Rate loop_rate(1);
  while (ros::ok()) 
    ROS_INFO("I heard: [%s]", copyListener.getText().c_str());
    ros::spinOnce();
    loop_rate.sleep();
  

  return 0;

getText() 方法没有任何价值。见下面的输出:

[0x7ffc5698a2b0] constructor called
[0x7ffc5698a2d0] copy constructor called
[ INFO] [1549031938.250136695]: I heard: []
[ INFO] [1549031939.250183378]: I heard: []
[ INFO] [1549031940.250170333]: I heard: []
[ INFO] [1549031941.250176834]: I heard: []
^C[0x7ffc5698a2d0] destructor called
[0x7ffc5698a2b0] destructor called

我猜复制构造函数缺少一些东西。 在构造函数中使用关键字“this”时如何定义复制构造函数?

【问题讨论】:

保存节点处理程序并在复制构造函数和赋值函数中重新绑定回调? 我知道缺少什么:MCVE。可能nh.subscribe 需要再次调用,或者ros::Subscriber 不打算被复制。 所以大概当你复制你的监听器时,副本监听器会获得订阅者的副本,但是订阅者与创建第一个订阅者时评估的“this”具有相同的绑定,即它正在更新 _text在原始侦听器中,而不是副本侦听器中。 【参考方案1】:

你需要两个Subscribers,一个通知原始TextListener对象,一个通知复制TextListener

您确实有两个订阅者,但由于副本 TextListener 中的一个是原始订阅者的副本,因此它们都更新了原始 TextListener 的 _text 成员。

我找不到比在 TextListener 中保留对 NodeHandle 的引用并让复制构造函数重新订阅 NodeHandle 而不是复制原始对象的订阅(调用原始对象的回调)更好的方法。

【讨论】:

非常感谢。我听从了你的建议,它就像一个魅力!

以上是关于在构造函数中使用关键字“this”时定义复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript面向对象简介

带有“this”关键字的Java复制构造函数[重复]

this作为构造函数时注意点

类和对象

复制构造函数中的c ++用户定义成员

this和super关键字在构造器中放置第一行的原因