【问题标题】:Circular dependency with the relationships "contains" and "is in"具有“包含”和“在”关系的循环依赖
【发布时间】:2018-06-03 19:41:48
【问题描述】:

我想就以下问题收集您的意见。

我们有一个名为“Room”的类。每个房间可能包含“Person”类的零个或多个实例,因此 Room 存储一个 Person 集合(例如向量)。它拥有他们。但是,在 Room 之间移动 Person 有一些耗时的逻辑,因此 Person 还包含他们当前所在的 Room。它只是一个 没有所有权的指针。这个信息在理论上是多余的,因为可以从房间里的 Persons 集合中得到它,但是假设房间数很大 >> 人数,这样的操作会很慢......

class Room {
std::vector<Person> peopleInside;
};

class Person {
Room* currentRoom; //could be shared_ptr to avoid raw pointers
};

当然,它更复杂(类比这更多),但我已尽可能简化它。

我的问题是:

1) 在这种情况下,这本身是循环依赖吗?

2) 这个解决方案对您来说是否肮脏/不优雅?

3) 是否值得换成别的东西?

【问题讨论】:

  • 如果人们经常在房间之间移动,我认为向量 可能是一个不好的选择。
  • 我不喜欢的是这种设计会给出不一致的状态,即房间 A 中的人可能指向房间 B。但是要评估是否可以避免这种情况,有必要使用一些用例描述,即对数据进行什么样的操作?例如,我想一个操作是将人 X 移动到房间 A,对吗?那么如何抓到人呢?要搜索的名称?你如何获得 Room A。你有 Room 的向量吗?
  • 是的,我同意这两者 - 存储直接对象会导致复制过多并且可能出现不一致的状态。我有一张房间和它们之间的过渡图。如果有过渡,一个人可能会移动到相邻的房间,移动是一个动作(就像在游戏中一样),游戏逻辑将更新集合以使它们同步......但我自己看到了这种设计的弱点。 ..
  • 你能描述一下为什么 Person 需要了解 Room 吗?从您评论中的描述来看,您的控制器似乎已经知道涉及哪些房间。
  • @4386427 这可能很方便。否则,如果您手头只有Person,您将不得不询问您的Rooms 容器(无论是什么),以找到该人当前所在的Room,这将涉及某种搜索。

标签: c++ architecture software-design


【解决方案1】:

这个问题确实需要在上下文中进行研究。如果Persons 只存在于Room 的上下文中,那么反向指针是安全的。当 Room 被销毁时,Persons 也会被销毁(繁荣!)所以不会出错。

但我怀疑这太简单了。 Room 的声明更可能是这样的:

class Room {
    std::vector<std::shared_ptr<Person>> peopleInside;
};

现在我们有一个可能的“悬空指针”问题,你不能用Person 中的std::shared_pointer&lt;Room&gt; 解决这个问题,因为你确实有一个循环依赖,shared_ptr将永远能够删除它正在管理的对象(因为Room 持有对Person 的引用,反之亦然,因此,死锁)。

因此,请像这样声明 Person:

class Person {
    std::weak_ptr<Room> currentRoom;
};

并从一些shared_ptr&lt;Room&gt; 初始化currentRoom,当Room 存在时你保持可用。这打破了循环依赖。

要取消引用currentRoom,您可以这样做:

if (auto room_I_am_currently_in = currentRoom.lock())
{
    room_I_am_currently_in->OpenDoor ();
}

如果原来的shared_ptr&lt;Room&gt; 已被销毁,那么lock 将失败。当room_I_am_currently_in 超出范围(实际上是shared_ptr&lt;Room&gt;)时,锁将被释放。

要将一个人转移到另一个房间,只需重新分配currentRoom。

更多关于std::weak_ptrcppreference的信息。

【讨论】:

    猜你喜欢
    • 2014-09-06
    • 2011-03-23
    • 2013-01-11
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2023-04-06
    相关资源
    最近更新 更多