c++ - 在构造函数中注册weak_ptr观察者
问题描述
我正在尝试重写我们的 Observer / Observable 实现以使用 std::shared_ptr/std::weak_ptr 来摆脱代码中当前存在的一些讨厌的竞争条件。
通常,观察者会在满足某些条件或构造子对象时注册自己,如下所示:
// Used to be raw 'this' now child instead derives a weak_ptr and stores it
child->addObserver(shared_from_this())
并像这样在析构函数中注销自己:
child->removeObserver(this); // Not shared_from_this() since in destructor
在某些情况下,这可以正常工作,但是在许多情况下,观察者希望在构造函数中注册自己。由于尚未创建 shared_ptr,我们无法调用 shared_from_this()。
由于通常建议使用 weak_ptr 在 C++ 中实现观察者模式,我想知道解决上述问题的惯用方法是什么。
一些想法:
- 让创建观察者对象的工厂注册观察者。这泄露了观察者的抽象(为什么工厂应该知道孩子想要观察谁?)并迫使观察者暴露它可能想要观察的内部对象
- 添加一个在构造函数完成后由工厂调用的 init 方法,比上面更好,但是构造函数和 init 之间的语义区别是什么?应该在哪里做?它甚至是RAII吗?事实上,有些语言甚至将它们的构造函数称为 init。
- 将 lambda 传递给构造函数,该构造函数接受另一个在构造后调用的 lambda
- 也许是一些模板魔法?
- 以其他方式实现观察者模式。
解决方案
处理您所要求的问题的一种方法是创建一个由 a 持有shared_ptr
并包含在“父级”中的显式观察者对象实例。观察者对象会将观察结果发送给父对象。
然而,由于孩子正在shared_ptr
向 a注册 a weak_ptr
,实际上父母不需要明确地将自己作为观察者移除。当孩子向观察者发送通知时,它首先检查是否weak_ptr
有效。如果不再有效,可以原地移除观察者而不是通知。
void notify_observers (Event e) const {
auto o = observers_.begin();
auto erase = [this](decltype(o) o) {
return observers_.erase(o);
};
while (o != observers_.end()) {
if (auto l = o->lock()) ++o, l->notify(e);
else o = locked_call(erase, o);
}
}
推荐阅读
- javascript - 搜索栏网站:按页面标题而不是页面链接 Javascript 搜索
- c - struct hostent 代表什么?
- react-native - 构建失败并在 react-native-navigation 包中出现异常
- mongodb - 反应式存储库不保存对象
- c# - 将 Json 嵌套对象反序列化为类级别属性而不是类对象
- javascript - 如何执行第二个 jQuery 片段以添加 html 代码
- sql - 左连接后计算所有的 SQL 查询
- swift - Swift - 从 GADBannerView 扩展后出现无法识别的选择器错误
- javascript - 等到它完成回调函数的执行
- c# - 我可以从母版页启动一个弹出窗口以使其在所有页面上保持打开状态吗?或者它到底应该在哪里?