传递 shared_ptr 到 std::function (成员函数)

4
以下观察者类通过调用attach将回调函数与主题注册,当其构造函数执行时。我希望观察者的析构函数可以取消注册回调函数。
如何传递与attach相同的指针给detach,以便主题可以将其从其观察者列表中删除?
我想我必须存储一个指向thisshared_ptr,但我不确定如何从中获取到成员函数callbackshared_ptr
有谁可以帮忙吗?
Observer::Observer(Subject& subject) : m_subject(subject),
{
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

Observer::~Observer()
{
    // I tried this initially but realised that the pointer below
    // is different to the one passed to `attach` from the ctor.

    m_subject.detach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

void Observer::callback()
{
    // do some stuff
}

attachdetach的声明如下:

void Subject::attach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);

void Subject::detach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);

你为什么在构造函数参数列表中不使用 const Subject&?因为你显然还是要复制一份的。 - Superlokkus
@Superlokkus 因为 Subject::attach 不是 const - ksl
那么 m_subject 也是一个 Subject & 吗?否则你会创建主题的副本,然后它就无关紧要了。 - Superlokkus
是的,m_subject 是一个 Subject& - ksl
只是想确保您得到您想要的 :-)。请不要忘记标记一个已接受的答案;-) ) - Superlokkus
2个回答

1
我建议在观察者类中也存储一个shared_ptr的副本,可以作为成员变量。这样你就可以使用它来将相同的指针传递给detach函数。

像这样:

class Observer {
    //Other Stuff here

private:
    std::shared_ptr<std::function<void()>> callback_ptr;
};

Observer::Observer(Subject& subject) : 
m_subject(subject), 
callback_ptr(std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))
{
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

Observer::~Observer()
{
    m_subject.detach("cmd", callback_ptr));
}

值得注意的是,正如@dkg所提到的,make_shared 每次调用都会返回一个新的 shared_ptr,因为它的目的是“创建一个带有以下参数的新对象并返回一个 shared_ptr”。大致相当于 shared_ptr(new std::function<void()> (std::bind(&Observer::callback, this))。 为什么会有额外的 make_shared 函数呢?这是为了最小化分配并保证在长表达式中的异常安全性。 如果你只想共享一个对象,则只需分发您的 shared_ptr副本

1
那就是解决方案。否则,在 dtor 中使用 make_shared 创建一个新实例,并且传递的共享指针将指向此新实例,而不是在 ctor 中创建的实例... - Baris Akar

1
每次调用 std::make_shared 都会为您分配和构造一个新对象。
在您的代码中,您调用了两次,然后您有两个不同的对象实例。
您可以调用一次并将共享指针作为类的成员保留。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接