【问题标题】:Static Singleton?静态单例?
【发布时间】:2012-12-06 19:52:20
【问题描述】:

是否可以制作通用单例?我想创建一些我可以继承的东西并获得单例的功能。我在使用带有静态成员的模板时遇到了问题。

这不应该工作吗?

**

更新

**

感谢到目前为止的回复。所以现在我的问题是 GameEngine 看不到它自己的构造函数。我知道它是私人的,但仍然如此。

Singleton.h

template <typename T>
class Singleton
{
private:
    static std::shared_ptr<T> m_Instance;
public: 
    static std::shared_ptr<T> Instance();
};

template<typename T>
std::shared_ptr<T> Singleton<T>::m_Instance = nullptr;

template<typename T>
std::shared_ptr<T> Singleton<T>::Instance()
{
if(m_Instance == nullptr)
    m_Instance = std::make_shared<T>();

return m_Instance;
}

GameEngine.h

class GameEngine : public Singleton<GameEngine>
{
private:
GameEngine();

};

【问题讨论】:

  • (1) 为什么你认为你需要一个单例? (2) 如果你使用单例,为什么要使用shader_pointer?这不像单例会被破坏,所以你可以剪掉那部分并只使用参考......
  • 为什么要将模板代码放在 *.cpp 中?
  • 每当您发布有关编译器错误的问题时,请包括 completeunedited 错误列表。另外,请指出错误在代码中的哪里,因为它可能很难甚至不可能计算行数。
  • 你需要一个单例吗?单例提供了三个完全独立的东西,但它试图将它们作为一个包提供。如果您不应该被允许复制您的课程,请使其不可复制。如果多次实例化你的类应该是一个错误,检测那个错误并抛出一个异常(如果你可以构造不止一次,为什么要阻止它?)。如果您需要一个全球可用的实例,请创建一个。这些都不意味着其他两个。
  • @GManNickG:将单例创建为全局变量的问题在于,如果一个人使用来自不同翻译单元的另一个翻译单元,那么它们的创建顺序是未定义的,因此这会导致未定义的行为。如果您使用我的答案中显示的局部静态变量模式,那么单例将以正确的顺序延迟初始化。

标签: c++ templates static


【解决方案1】:

我不知道它是如何工作的,因为没有什么可以阻止您创建更多 GameEngine 实例。

即使有可能(并且确实)有一种通用的方法来创建单例(可能涉及宏),我还是建议不要这样做,因为您真正需要单例的情况很少见 .让我换个说法……您真正真正需要单身人士的情况很少见。

【讨论】:

  • 我同意他们应该很少,但问题是为什么不。
  • 对于大多数程序我都同意。但是,您永远不会希望在同一个进程中运行两个游戏,因此您最好只使用全局变量来处理某些事情,而不是传递指针。它让事情变得更简单,而且可能会更快一点。
  • @JoshElias:问题很可能是“如何”,但 StackOverflow 最好的事情之一是它对这么多人有帮助的原因之一,因为通常当人们许多经验怀疑提出了错误的问题,他们会提出来并提出正确的问题。
  • 只是我每次在单例上寻找解决方案时,总是在争论是否应该使用它们。似乎没有具体的答案。如果有明显更好的方法来设计一个全局且独特的管理器类,那么请指出正确的方向。
  • @JoshElias 我不是这么说的。在某些情况下,我并不反对单身人士。我的意思是,如果您实施一种自动创建它们的机制,那么您就走错了路。如果您有几个单例,则不需要这种机制,您可以单独编写它们。如果你有很多,甚至想要一种机制来自动创建它们,那么你有 99% 的把握在错误的轨道上。
【解决方案2】:

创建单例的最佳方法如下:

class GameEngine
{
public:
    static GameEngine& instance() { static GameEngine e; return e; }

private:
    GameEngine() {}
    GameEngine(const GameEngine&) = delete;
};

e 变量将在第一次调用实例时(线程安全地)初始化,并在有序进程退出时被销毁。私有/删除的构造函数防止创建第二个实例。

【讨论】:

  • 你能解释一下这个 e 变量或者有什么好的文档吗?我很困惑它是如何初始化的。
  • 称为局部静态变量。变量的名称在块的本地范围内,但存储持续时间是全局的。它会在函数第一次被调用时被构造,但在程序的剩余生命周期中都会保留。
  • 显然删除构造函数和析构函数有区别?
  • 那是删除了默认的拷贝构造函数,这样别人就不能取单例的拷贝了。
  • 您需要打开 C++ 2011 支持。我认为这是您的编译设置中的一个开关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 2011-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多