这是我关于堆栈溢出的第一个问题,所以要温柔。
让我首先解释一下我希望看到的确切行为。如果您熟悉 C#,那么您就会知道将变量声明为“只读”允许程序员只为该变量赋值一次。进一步尝试修改变量将导致错误。
我所追求的:我想确保我定义的任何和所有单例类都可以在我的程序中准确地实例化一次(更多细节在底部)。
我实现目标的方法是使用 extern 来声明对单例的全局引用(稍后我将在我选择的时间实例化它。我看起来像这样,
namespace Global
{
extern Singleton& mainInstance; // not defined yet, but it will be later!
}
int main()
{
// now that the program has started, go ahead and create the singleton object
Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name
Global::mainInstance = Singleton::GetInstance(); // doesn't work either :(
}
class Singleton
{
/* Some details ommited */
public:
Singleton& GetInstance()
{
static Singleton instance; // exists once for the whole program
return instance;
}
}
然而,这并没有真正起作用,我不知道从这里去哪里。
关于我所反对的一些细节:
我担心线程,因为我正在编写将处理游戏逻辑的代码,同时与几个第三方进程和我将创建的其他进程进行通信。最终,我将不得不实现某种同步,以便多个线程可以毫无顾虑地访问 Singleton 类中的信息。因为我不知道我可能喜欢做什么样的优化,或者线程究竟需要什么(从未使用它做过真正的项目),我认为能够在实例化单例时可预测地控制将是一件好事。
想象一下,如果流程 A 创建流程 B,其中 B 包含多个针对多个文件和/或库分布的单例。如果我不能可靠地确保这些单例对象被实例化的顺序(因为它们可能相互依赖,并且在 NULL 对象上调用方法通常是一件坏事),那可能是一场真正的噩梦。
如果我在 C# 中,我只会使用 readonly 关键字,但是有什么方法可以在 C++ 中实现这个(编译器支持的)行为?这甚至是个好主意吗?感谢您的任何反馈。
编辑
如果我被锁定在上面的代码示例中,选择的答案将是做我需要的最简单的方法。尽管我只打算制作这些 EntryPoint 对象之一,但我还是决定将模式从单例中改变。
class EntryPoint
{
/* Intentionally defined this way to discourage creation */
EntryPoint(const EntryPoint &); // undefined & private
EntryPoint& operator=(const EntryPoint &); // undefined & private
// public
EntryPoint()
{
/* All of the action is performed here! */
}
/* Other supporting functions */
}
// The easier to understand main function!
int main()
{
EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint
delete ep;
}
我认为我需要所有这些单例的原因之一是我计划创建一个更大的架构来支持模块化插件类型的应用程序。我还想要更多的错误检查和内存保护,以尽量减少内存泄漏。我很高兴地发现跨平台的 Qt ( http://qt.nokia.com/ ) 提供了保护指针和其他很酷的特性。