繁体   English   中英

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

[英]C++: Should I use global variables or class member pointers to communicate between modules?

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

我需要这些类进行通信(以便能够通过指针访问另一个类),并且我想以最佳方式实现这一点。

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

  • 如果子系统X需要访问子系统Y,则在类X中添加一个指向Y实例的成员变量。创建X时,将指向Y的指针传递给它,并设置成员变量m_pSystemY

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

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

我的问题:

  • 我的游戏引擎项目应使用以下哪种解决方案?

  • 你们中的任何人是否有使用这些方法的亲身经历?

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

真有趣,我在每个方向上看到一个答案!

无论如何,我建议您在选项#1(向类X添加成员变量以指向Y的实例)之后执行以下操作,并进行一些小的修正: 使用interface代替

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

创建模块A后,如果需要使用模块B的功能,则可以执行setModuleBHandler(moduleB)

这样,您可以更改执行所需功能的模块,而调用方无需注意(因为仍然尊重该接口)。

这将使您可以遵循其他良好做法,例如TDD。

例:

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

这几乎是相同的。 以前起作用的仍然可以起作用。 不同之处在于,现在您可以使用一些完全不同的Logger实现,而不必担心会影响使用它们的各种模块的影响。

例如,可以有一个实现接口的TextLogger类和另一个实现相同接口的DBLogger。 您可以互换它们而不会遇到任何问题。

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

我知道这个小例子并不能正确显示此选择的全部优点,很多人都可以找到其中的缺点,但是我坚信这是大多数情况下的最佳选择(当然,每种情况都是案件)。

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

我会选择子系统管理器类。 我将使用模板来实现此目的,并确保子系统实现相同的接口(即c#lingo不确定c ++等效项是什么),以便它们都可以相互通信。

如果您的类总是只具有一个实例,则可以将它们视为单例:

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;
  }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM