假设我们的设计模式与此类似:
#include <set>
class Receiver;
class Transmitter {
public:
Transmitter() = default;
virtual ~Transmitter() {
for(auto recv : m_receivers){
recv->setSource(nullptr);
}
}
const std::set<Receiver*> getReceivers(){
return m_receivers;
}
private:
std::set<Receiver*> m_receivers;
};
class Receiver {
public:
Receiver() = default;
Receiver(const Receiver& other){
setTransmitter(other.m_trans);
}
~virtual ~Receiver(){
setTransmitter(nullptr);
}
void setTransmitter(Transmitter* tr){
if(m_trans) m_trans->m_recv.erase(this)
m_trans=tr;
if(m_trans) m_trans->m_recv.insert(this)
}
private:
Transmitter* m_trans = nullptr;
};
这似乎是Observer pattern:两个类之间的关系为1:M,并且两者相互引用。
现在想象我们要使它们与std::vector
或任何其他类似的std
容器兼容。因此,它必须是可复制构造的(或可移动的)。
Receiver
可以复制(如上面的代码所示),但是,发送器会出现问题。我曾考虑过其他选择,但我无法决定该怎么做:
还是应该简单地禁止复制和移动初始化? (无法解决问题)
有一个similar question in stack overflow about this problem in Java。但是对于C ++,答案可能会改变
答案 0 :(得分:3)
移动构造函数将是合适的:
Transmitter(Transmitter&& other) noexcept : m_receivers(std::move(other.m_receivers)) {
for (auto recv : m_receivers) {
recv->m_trans = this;
}
}
移动之所以有效,是因为在移动之后,新对象应该与从其移出的对象相同,因此从观察者的角度来看,发射器没有改变。
与Java不同的原因是Java没有移动构造函数,因此没有(简单)的方式来表达“窃取观察者/资源”。