在构造函数中注册weak_ptr观察者 [英] Registering weak_ptr observer in constructor
问题描述
我正在尝试重写我们的Observer/Observable实现,以使用std :: shared_ptr/std :: weak_ptr摆脱代码中当前存在的某些讨厌的竞争条件.
通常,观察者在满足某些条件时或在构造子对象时进行注册,例如:
//以前是原始的'this',现在,子级派生weak_ptr并将其存储子> addObserver(shared_from_this())
然后像下面这样在析构函数中注销自己:
child-> removeObserver(this);//自从析构函数以来,不是shared_from_this()
在某些情况下,它可以正常工作,但是在许多情况下,观察者希望在构造函数中进行注册.由于尚未创建shared_ptr,因此我们无法调用shared_from_this().
由于通常建议使用weak_ptr来在C ++中实现观察者模式,所以我想知道解决上述问题的惯用方式是什么.
一些想法:
- 让创建观察者对象的工厂注册观察者.这会泄漏观察者的抽象(工厂为什么要知道孩子想观察谁?),并迫使观察者暴露可能要观察的内部物体
- 添加一个初始化方法,该方法在构造函数完成后由工厂调用,这比上面的方法更好,但是构造函数和init之间的语义区别到底是什么?在哪里应该做什么?甚至是RAII吗?确实,某些语言甚至将其构造函数称为init.
- 将lambda传递给构造函数,该构造函数将使用另一个在构造后被调用的lambda
- 也许有些模板魔术?
- 以其他方式实现观察者模式.
一种解决问题的方法是创建一个由 shared_ptr
持有并包含的显式观察者对象实例.在父母"中.观察者对象会将观察分派给父对象.
但是,由于子级正在将 shared_ptr
注册到 weak_ptr
,因此实际上父级不需要显式地将其自身删除.当孩子向观察者发出通知时,它会先检查 weak_ptr
是否有效.如果它不再有效,则可以在原位删除观察者,而不必进行通知.
void notify_observers(Event e)const {自动o = Observers_.begin();自动清除= [this](decltype(o)o){返回观察者_.erase(o);};while(o!= observers_.end()){if(auto l = o-> lock())++ o,l-> notify(e);否则o = locked_call(erase,o);}}
One way to deal with the problem as you have asked it is to create an explicit observer object instance held by a shared_ptr
and contained in the "parent". The observer object would dispatch observations to the parent.
However, since the child is registering a shared_ptr
to a weak_ptr
, there is actually no need for the parent to remove itself as an observer explicitly. When the child is sending out notifications to observers, it checks if the weak_ptr
is valid first. If it is no longer valid, it can remove the observer in situ instead of notifying.
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);
}
}
这篇关于在构造函数中注册weak_ptr观察者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!