使用智能指针的C ++组合

时间:2013-11-19 17:14:37

标签: c++ smart-pointers composition

我正在遵循游戏对象架构presented by Marcin Chady的设计。 作为快速摘要,Game Object类可以包含多个Attribute和Behavior子类实例。游戏对象也包含在Scene类中。这个图表可以澄清一些事情:

enter image description here

Behavior子类需要能够访问其父Game Object类。这是必需的,因为行为需要能够读取和写入各种属性并订阅从游戏对象接收事件。某些行为可能还需要访问其父游戏对象的场景,以便他们可以实例化其他游戏对象。

我目前正在使用共享指针和弱指针。例如,Game Object类包含vector<shared_ptr<Attribute>>vector<shared_ptr<Behaviour>>。然后,行为和属性类都包含weak_ptr<GameObject>。这打破了参考周期。

现在,如果一个行为想要访问场景,它需要执行一些嵌套的弱指针锁:

if (std::shared_ptr<GameObject> sharedGameObject = GetGameObject().lock())
{
    if (std::shared_ptr<Scene> sharedScene = sharedGameObject->GetScene().lock())
    {
        // Do something with the scene.
    }
}

这可能会有点混乱。如果我们需要访问Application类,则需要3个嵌套锁。使用原始指针时,这显然不是必需的。我使用正确的智能指针吗?如果我是,有什么我可以做的来整理这个或者这是我将要忍受的东西吗?

2 个答案:

答案 0 :(得分:1)

我认为你根本不需要任何智能指针,假设:

  • GameObject对象真正拥有 Attribute&amp; Behavior个对象或
  • GameObject对象的生命周期始终长于Attribute&amp; Behavior对象的生命周期。

或者考虑一下您的代码示例,请考虑以下问题:else节能做什么?他们会被处决吗?我认为答案是:“他们只做失败/错误检测和报告”,“不,我无法想象”。

如果你希望它是更现代的C ++外观,或原始指针或原始引用,你应该使用GameObject切换到std::reference_wrapper<T>类的内部引用。

答案 1 :(得分:1)

你真的想要智能指针吗?从第一次猜测, 基于设计层次结构(和名称):

  • 如果这是典型的层次结构,则只有一个 Application,不会动态分配,但会 是main中的局部变量。所以永远不会聪明 指向它的指针。

  • 所有Scene都属于Application,所以从设计中可以看出 谁拥有什么。在这两种情况下,它都是1到n的关系 意味着拥有对象中的指针需要在 容器。您可以使用std::unique_ptr,但事实并非如此 真的很有必要;事实上,它似乎有点混淆: 要删除某个对象,请不要使用delete,而是erase 容器。 (另一方面,使用原始指针,你可以 必须同时从容器中删除和删除它。它的 虽然我倾向于简单,但在很大程度上取决于你 原始指针。)

  • 如果这些类代表了我的想法,GameObject 由于外部事件而来来去去。这是典型的 没有现有智能指针相关的情况。 我猜大多数GameObject是由...创建的 Scene以回应某个事件;有些可能是由其他人创造的 GameObject。但一旦创建,他们管理自己的一生, 并且可能会在事件中被delete this删除 处理程序。 (当然,所有对他们一生感兴趣的物品 必须使用观察者模式注册为观察者。 但无论如何都是如此。)

  • EventDispatcher毫无疑问地指向任何对象 对事件感兴趣,但这些是用于导航。他们应该 是智能指针。这是每个人的责任 使用EventDispatcher注册和撤消的对象 根据它感兴趣的事件 - 而不是 很明显,它会解析析构函数中的所有内容, 因为死对象对任何事件都不感兴趣,但它 也将(可能)在其他时间注册和退出 同样。

请注意weak_ptr的必要性通常是好的 指示引用计数指针不是解决方案 你正在寻找。