首页 > 解决方案 > 将这个包装在智能指针中的问题传递给 C++ 中的方法

问题描述

我有 2 个相互依赖的类(循环依赖)。一个只是一个对象Person,另一个监听对象的变化PersonListener。该类Person定义如下。

class Person {
 private:
  std::string name;
  PersonListener listener;
 public:
  Person(std::string name, PersonListener listener) : name{name}, listener{listener} {};
  void setName(std::string name) {
   this->name = name;
   auto sPointer = std::make_shared<Person>(*this); // problem here? makes a copy?
   listener.nameChanged(sPointer); // how do I pass this by reference?
  }
}

PersonListener定义如下。

class PersonListener {
 public:
  PersonListener() {}
  void nameChanged(std::shared_ptr<Person> person) {
    std::cout << "changed" << std::endl;
    // some mutation to person would occur here
    // the way I am passing this of the Person does not allow me to reflect mutations
  }
};

问题在于thisPerson实例传递给PersonListener. 当PersonListener改变传入的共享指针时,不会反映更改。

我目前的解决方法是重载PersonListener.nameChanged使用void nameChanged(Person *person)原始指针。这种方法很好,但这会带来尴尬,因为我几乎在任何地方都使用智能指针,然后在这里使用原始指针(请注意,在我的真实示例中,传入原始指针也会在代码的其他地方产生影响)。

标签: c++pointersthislistenersmart-pointers

解决方案


auto sPointer = std::make_shared<Person>(*this); // problem here? makes a copy?

是的,它确实。

很容易想到使用

listener.nameChanged(std::shared_ptr<Person>(this));

但随后,this成为 的托管对象shared_ptr,这是不对的。

我看不出你不能使用的任何理由

class PersonListener {
    ...
    void nameChanged(Person& person) { ... }
};

并调用它

listener.nameChanged(*this)

更新,以回应OP的评论

如果必须使用shared_ptr,则可以在构造 时使用 noop 删除器shared_ptr

std::shared_ptr<Person> sPointer(this, [](Person* ptr) {});
//                                     ^^ The deleter. It doesn't do anything.
listener.nameChanged(sPointer);

推荐阅读