考虑以下类结构:
struct owner;
struct owned;
struct owned {
owner* my_owner;
};
struct owner {
owned owned_object;
};
类owned
仅用作owner
的成员,对于所有owner
个对象o
,以下不变量应保留:
o.owned_object.my_owner == &o;
我的问题是:
owner
/ owned
的构造函数的编程实践?对于2.,我的重点是简单而优雅的代码,而不是一流的效率。例如,我想尽可能多地使用隐式声明的构造函数。
PS:这个问题可以看作Pointer to owner class的后续行动。
答案 0 :(得分:1)
我不确定是否有实际名称,因为它不是一个非常有用的模式,因为它非常有限:类现在完全依赖于两个方向。好的一面是,这是一个简单的解决方案,不好的一面是,这是circular dependency的一个例子,可以看作是反模式。
如果您要创建一个界面IOwnedOwner
(不是一个有用的名称,但描述当前情况),让所有者继承并让拥有使用该界面,那么您将拥有回调系统。至少在这里,任何想要拥有的人,都必须从界面继承。
使用Observer pattern,所有感兴趣的各方都可以注册来自所拥有对象的通知,这将使其更加灵活。
答案 1 :(得分:0)
在上面显示的情况下,有一个简单的问题解决方案:在owner
类中,引入指针copy_
并修改复制构造函数/赋值运算符,使copy_
始终指向owner
对象的最后一个副本。复制owned
时,我们会通过old_object.my_owner.copy_
获取新对象的地址。
为了最大化代码重用,我们引入了owner
基类和owner_ptr
类,如下所示。
class owner {
public:
owner() = default;
owner(const owner& to_copy) { to_copy.copy_ = this; }
owner& operator=(const owner& to_copy) { to_copy.copy_ = this; return *this; }
private:
mutable owner* copy_;
template<class> friend class owner_ptr;
};
template<class Owner>
class owner_ptr {
public:
owner_ptr(Owner* o) : owner_(o) {}
owner_ptr(const owner_ptr& to_copy) : owner_(to_copy.owner_->copy_) {}
owner_ptr& operator=(const owner_ptr& to_copy) { owner_ = to_copy.owner_->copy_; return *this; }
Owner& operator*() const { return static_cast<Owner&>(*owner_); }
Owner* operator->() const { return static_cast<Owner*>(owner_); }
private:
owner* owner_;
};
现在获得所需的所有者/拥有的关系只需要对原始代码进行微小的更改。
struct some_owner;
struct some_owned;
struct some_owned {
some_owned(some_owner* o) : my_owner(o) {}
owner_ptr<some_owner> my_owner;
};
struct some_owner : owner {
some_owner() : owned_object(this) {}
some_owned owned_object;
};
但是这种方法有一些注意事项:
some_owner
个对象的所有副本必须按顺序发生,即没有多线程副本,也没有来自同一对象的嵌套副本。 some_owner
类涉及移动some_owned
类时才有效。如果不是这种情况,例如当some_owned
存储在向量中时,我们必须为移动owner
类的事件实现旧式观察者模式。然后,编码owner
和owner_ptr
会更加有效,但生成的代码与以前一样简单,并且开销只会稍微增加。