指向所有者的指针

时间:2014-09-22 08:21:51

标签: c++ c++11

考虑以下类结构:

struct owner;
struct owned;

struct owned {
    owner* my_owner;
};

struct owner {
    owned owned_object;
};

owned仅用作owner的成员,对于所有owner个对象o,以下不变量应保留:

o.owned_object.my_owner == &o; 

我的问题是:

  1. 此模式是否有名称?
  2. 是否有关于如何最好地实现owner / owned的构造函数的编程实践?
  3. 对于2.,我的重点是简单而优雅的代码,而不是一流的效率。例如,我想尽可能多地使用隐式声明的构造函数。

    PS:这个问题可以看作Pointer to owner class的后续行动。

2 个答案:

答案 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类的事件实现旧式观察者模式。然后,编码ownerowner_ptr会更加有效,但生成的代码与以前一样简单,并且开销只会稍微增加。