【问题标题】:How to declare an static instance of a Class in C++?如何在 C++ 中声明类的静态实例?
【发布时间】:2013-10-08 10:18:35
【问题描述】:

几个月前,我创建了一个名为 Vexed 的游戏的 C# 项目。现在我正在创建一个俄罗斯方块,但在 C++ 中。基本上我想使用我在另一个项目中使用的相同逻辑,它有点像这样:

我创建了一个名为“游戏”的类,其中包含有关游戏的所有信息。它有它的方法、变量和一切。然后,我创建了一个名为“PublicInstances”或类似名称的静态类,并在该类中声明了如下内容:

static class PublicInstances
{
    public static Game vexedGame = new Game(); //This is C# and works.
}

当时使用起来非常简单,因为我对游戏所做的任何更改都保存在我的类的静态实例中,我可以在项目的任何地方访问它。我想知道如何用 C++ 准确地做到这一点,以创建我的类 Game 的公共或全局实例,以便我可以访问它并在任何地方更改它,并在我的项目的任何表单或类中更新所有内容。非常感谢您的帮助。

//如果我的英语不是最好的,请见谅^^

【问题讨论】:

  • 如果你真的想要一个全局的,你不必把它放在一个类中。只需在头文件中声明并在源文件中定义。但是全局变量(或全局可访问的静态变量)通常是糟糕的设计
  • 我的主要问题是我经常在Forms之间穿梭,我需要从一个地方到另一个地方获取信息,如何更改全局变量或类的使用?
  • 听起来TetrisGame 应该是一个命名空间,而不是一个对象。这也将消除为它定义类类型的需要。
  • 我同意这个设计可能有点缺陷的事实,但这不是问题。无论如何,我仍然建议您重新考虑。

标签: c# c++ class static global-variables


【解决方案1】:

重温和总结

选项 1

您可以简单地声明和定义 Game 对象的全局实例。 在头文件中,例如游戏.h:

extern Game globalGameObj;

当您在源文件中包含 game.h 时,globalGameObj 名称变得可见。 您还需要创建一个实际对象。在源文件中,例如game.cc(任何类之外):

Game globalGameObj;

通过变量名访问:

globalGameObj.do_some_work();

选项 2

使用通常称为单例的模式。将以下内容添加到您的 Game 类 (game.h):

class Game
{
  public:
    static Game &shared_instance() {static Game game; return game;}

  private:
    // Make constructor private. Only shared_instance() method will create an instance.
    Game() {/*whatever initialisation you need*/}
};

您使用 shared_instance() 方法访问游戏实例:

Game::shared_instance().do_some_work();

您没有在上面使用类似static class PublicInstances 的东西。 C++ 允许您引入一个命名空间(例如 PublicInstances)来提供名称隔离并将您的全局对象保存在一个地方,但这可能是一种矫枉过正的做法。无论如何,如果您的全局对象很少,那么它很可能是一个糟糕的设计。

哪个选项更好?有些人会争辩说应该使用单例模式。它保证只创建一个实例。然而,选项 1 和选项 2 都有相同的问题:它们在代码中引入了一个全局对象,而所有缺点都归因于全局变量。我会说单例是变相的全局对象。我看不出支持这两种选择的技术原因,所以我会说这是个人喜好问题。

历史记录:)

我对选项 2 的第一个建议是使用动态分配的游戏对象而不是函数本地静态对象。

static Game *instance() {if (!_inst) _inst = new Game(); return _inst;}

很少有人认为这不是最好的方法了,谢谢KalargiopewebSimple。 C++03 在存在线程的情况下初始化静态对象存在问题。 C++11 保证静态的安全初始化。

C++11 草案,第 6.7 节

这样的变量在控件第一次通过其声明时被初始化; 这样的变量在其初始化完成时被认为已初始化。 [...] 如果在初始化变量时控制同时进入声明, 并发执行应等待初始化完成。

【讨论】:

  • 你已经声明了S::_inst,但你还没有定义它。
  • 还有一个更好的方法是static S& instance() { static S inst; return inst; }
  • @BenVoigt 不清楚你的意思,不需要上课。游戏类默认存在。
  • @dmitri 其实你可以;第一次调用函数时调用ctor。您也可以将参数传递给ctor,就像static S inst { 1, 2 }; 或其他任何东西
  • 关于选项 #2 的缺点,根据 n2660,C++11 不再是这种情况:open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多