重新审视和总结
选项1
您可以简单地声明并定义一个全局的Game对象实例。
在头文件中,例如game.h:
extern Game globalGameObj;
当你在源代码文件中包含game.h时,globalGameObj名称会变得可见。
你还需要创建一个实际的对象。在源代码文件(例如game.cc)中(不属于任何类):
当您在源文件中包含game.h时,全局变量globalGameObj的名称就会变得可见。
此外,您还需要创建一个实际的对象。在源文件中(比如game.cc)(不属于任何类):
Game globalGameObj;
通过变量名访问它:
globalGameObj.do_some_work();
选项2
使用经常被称为单例的模式。在您的游戏类(game.h)中添加以下内容:
class Game
{
public:
static Game &shared_instance() {static Game game; return game;}
private:
Game() {}
};
您可以使用 shared_instance() 方法来访问 Game 实例:
Game::shared_instance().do_some_work()
在上面的代码中,您没有使用类似于static class PublicInstances
的东西。C++ 允许您引入命名空间(例如PublicInstances)以提供名称隔离并将全局对象保留在一个位置,但这可能会过度设计。无论如何,如果您只有少量的全局对象,那么很可能是一个不好的设计。
哪个选项更好?一些人会认为应该使用单例模式。它保证只创建一个实例。然而,选项 1 和选项 2 都有相同的问题:它们在您的代码中引入了一个全局对象,带有所有归因于全局变量的缺点。我会说单例模式是伪装成全局对象的东西。我没有看到任何技术上有利于任何一种选项的原因,所以我认为这是个人口味的问题。
历史注记 :)
对于选项 2,我的第一个建议是使用动态分配的 Game 对象而不是函数局部静态对象。
static Game *instance() {if (!_inst) _inst = new Game(); return _inst;}
有些人提出这不再是最好的方法,感谢Kal、argiopeweb和Simple。在存在线程的情况下,C++03存在初始化静态对象的问题。C++11保证了静态变量的安全初始化。
C++11草案第6.7节
如果这样的变量在其声明中首次通过控制,则将初始化此类变量;
只有在其初始化完成后才被认为已初始化[...]。 如果在变量正在初始化时并发地进入声明,
并发执行应等待初始化完成。
TetrisGame
应该是一个命名空间,而不是一个对象。这也将消除为其定义类类型的需要。 - Ben Voigt