避免循环引用

时间:2015-06-19 13:58:55

标签: c++ sdl

我正在用SDL构建一个小游戏。我有一个类GameObject,它是在游戏中表示对象的主要类。我可以从外部注入的组件解决了不同的行为:

#include "Input.h"
class GameObject
{
public:
    void setInput(Input* input)
    {
        input->setGameObject(this);
        this->input = input;
    }
}


class GameObject; // cannot #include "GameObject.h"
class Input
{
private:
    GameObject* object;
public:
    void update(float elapsedTime)
    {
        // do fancy stuff on the GameObject object
    }
    void setGameObject(GameObject* object)
    {
        this->object = object;
    }
}

Input类必须处理GameObject实例。我现在有一个循环参考,我猜这不是一个好主意吗?

编辑:我调整了我的示例以使其更清晰。我有一些像Input类这样的组件,我要使用这个class GameObject;语句,因为我不能包含头文件。 所以,如果我理解正确,我会有一个循环参考!?要解决这个问题,我必须使用一个接口并将其添加到setGameObject(InputInterface* object)。但我无法预测访问GameObject需要哪些功能/成员,因为使用了不同的组件(例如PlayerInputDemoInputAiInput,...)。

2 个答案:

答案 0 :(得分:0)

您似乎正在使用原始指针(我个人认为这是一个坏主意),因此我认为使用此循环引用没有任何问题,只需记住检查null。

如果您使用更智能的指针类型,在这种情况下,您将在一个方向上使用强引用("包含"另一个方向),在另一个方向上使用弱引用(仅在一个方向上使用弱引用)需要一种沟通方式。)

例如,您的游戏对象可能拥有输入机制;但输入机制只需要一种方法将输入传达给游戏对象。

  

std :: weak_ptr用于破坏std :: shared_ptr的循环引用。

请参阅:http://en.cppreference.com/w/cpp/memory/weak_ptr

另外,检查您的输入是否真的需要保留整个游戏对象,或者只是某个具有特定界面的对象。在这种情况下,事件机制或委托模式可以帮助您删除一些硬依赖项。

答案 1 :(得分:0)

循环参考或双面反应并不少见。

例如,假设我们有客户/服务器关系。基于客户端或服务器上的更改(例如,webapp),服务器可以决定更新客户端,或者客户端可以转发用户已经采取的需要客户端响应的活动或动作。无论哪种方式,两者都可能引用相同的数据或相互引用,这需要"引用..."还是他们?有时,从接口中解耦引用以修改引用所指向的数据会更有帮助。

对此的一般回应,就像网络通信一样,是异步I / O或消息传递,即使在游戏中这也不是一种不寻常的模式 - 通常,单人游戏可以利用消息 - 传递模型(想想SimCity的GlassBox模拟与#34;代理商"或MMORPG与实际网络消息/数据包)。

如果您关注"耦合,"也许您应该考虑各种异步技术来防止类内置回调到需要其定义的其他模块;回调/反应堆函数是一种非常常见的现象 - 我相信Boost.Signals2有一个很好的例子,说明如何使用它,以及std::async。另一种选择是简单地通过消息传递抽象所有内容,就像点对点网络一样,并使用消息传递/接收模块封装引擎的每个模块。这也可以使诊断更容易实现,前提是外部模块可以查看" peek"在消息的元数据。