C ++:我应该使用全局变量或类成员指针在模块之间进行通信吗?

时间:2011-03-01 23:40:39

标签: c++ design-patterns modularity

在我的项目中,我将多个子系统组织为类。

我需要这些类进行通信(因此能够通过指针访问另一个),我希望尽可能以最佳方式实现它。

我基本上在这里看到三种可能的解决方案:

  • 如果子系统X需要访问子系统Y,则将一个成员变量添加到指向Y实例的类X.创建X时,向其传递指向Y的指针并使其具有成员变量{{1} } set。

  • 为每个子系统声明一个全局变量m_pSystemY。它将在程序启动时填充指向新创建的子系统实例的指针。稍后,您可以从任何地方轻松访问它。

  • 创建复杂的子系统管理器类。所有子系统都存储在一个数组中。您需要调用函数才能访问特定的子系统。

我的问题:

  • 我应该将哪些解决方案用于我的游戏引擎项目?

  • 您是否有任何这些方法的个人经验?

5 个答案:

答案 0 :(得分:2)

通过指向其他类的指针暴露整个类将在整个系统中产生紧密耦合,从而打破了“demeter法则”。您可以通过已知的设计模式使其更好,例如:中介模式。只是一个想法...

答案 1 :(得分:2)

多么有趣,我看到每个方向都有一个答案!

无论如何,我建议您按照选项#1(将成员变量添加到指向Y实例的X类)进行一次小修正:使用界面

因此,每个模块都有一个接口。该界面将具有外部人员可能需要完成其工作的方法。其他一切都隐藏起来了。

创建模块A时,如果需要使用模块B的功能,您将执行类似setModuleBHandler(moduleB)的操作。

通过这种方式,您可以更改执行所需操作的模块,而无需调用者注意到它(因为接口仍然受到尊重)。

这将允许您遵循其他良好做法,例如TDD。

示例:

假设模块Broker需要记录(并且您有一个专用于记录的模块)。而不是声明public void setLogger(Logger logger),而不是声明如下:public void setLogger(LoggerInterface logger)

这几乎是一样的。以前的工作仍然有效。不同之处在于,现在您可以使用一些完全不同的Logger实现,而不必担心可能使用它们的无数模块中的影响。

例如,您可以使用实现接口的类TextLogger和实现相同接口的另一个DBLogger。您可以在不预期任何问题的情况下进行交换。

注意:使用抽象类会得到几乎相同的结果。

我知道这个小例子没有正确显示这个选择的全部优点,很多人都能找到它的缺点,但我坚信这是大多数情况下的最佳选择(当然每个案例是一个案例)。

答案 2 :(得分:0)

我根本不会使用全局变量。我会通过初始化函数将指针传递给其他系统。无论是谁实例化这些系统并初始化它们都可以决定如何存储它们,可以是它们自己的全局变量,静态类成员,单例包装器,或者(最合适的)某个统一类的成员(IE:类CGame)。无论哪种方式,在初始化时传递它们是最模块化,可读和可维护的,而不会以任何方式牺牲易用性。

答案 3 :(得分:0)

我会选择子系统管理器类。我将使用模板实现这一点,并确保子系统实现相同的接口(即c#lingo不确定c ++等价物是什么)所以他们可以互相交谈。

答案 4 :(得分:-2)

如果您的课程总是只有一个实例,那么您可以将它们视为单身:

class singleton
{
  // Private constructor
  singleton() {}
  // Static instance defaul to null in cpp
  static singleton *instance;

public:

  // Access function (put in cpp)
  static singleton* getInstance()
  {
    if(!instance) instance = new singleton();
    return instance;
  }
};