正如标题所说。我如何创建一个全局可用的类的实例(例如,我有一个打印的仿函数,我希望有一个这样的全局实例(虽然可以创建更多))。
答案 0 :(得分:18)
使用通常模式制作单个对象的所有努力都没有解决问题的第二部分 - 如果需要可以制作更多的东西。单身“模式”非常具有限制性,并不仅仅是另一个名称的全局变量。
// myclass.h
class MyClass {
public:
MyClass();
void foo();
// ...
};
extern MyClass g_MyClassInstance;
// myclass.cpp
MyClass g_MyClassInstance;
MyClass::MyClass()
{
// ...
}
现在,在任何其他模块中,只需包含myclass.h
并像往常一样使用g_MyClassInstance
。如果您需要制作更多内容,可以使用构造函数进行调用。
答案 1 :(得分:3)
首先,你想要全局变量是'代码味'(如Per Martin Fowler所说)。
但要达到你想要的效果,你可以使用单身人士的变体 使用静态函数变量。这意味着在使用变量之前不会创建变量(这会使您进行惰性求值),并且所有变量将以创建的相反顺序销毁(因此这可以保证将使用析构函数)。
class MyVar
{
public:
static MyVar& getGlobal1()
{
static MyVar global1;
return global1;
}
static MyVar& getGlobal2()
{
static MyVar global2;
return global2;
}
// .. etc
}
答案 2 :(得分:1)
作为对单例模式的略微修改,如果您还希望允许创建具有不同生命期的更多实例,则只需使ctors,dtor和operator = public。这样你就可以通过GetInstance获得单个全局实例,但是你也可以在堆或同一类型的堆栈上声明其他变量。
然而,基本思想是单身模式。
答案 3 :(得分:0)
Singleton pattern正是您要找的。 p>
答案 4 :(得分:0)
最简单和并发的安全实现是Scott Meyer的单例:
#include <iostream>
class MySingleton {
public:
static MySingleton& Instance() {
static MySingleton singleton;
return singleton;
}
void HelloWorld() { std::cout << "Hello World!\n"; }
};
int main() {
MySingleton::Instance().HelloWorld();
}
请参阅主题IV here,了解John Vlissides(来自GoF成名)的分析。
答案 5 :(得分:0)
Singleton是一个很好用的模式,但它有自己的缺点。在使用单身人士之前,请阅读MiškoHevery的以下博客。
答案 6 :(得分:0)
我更喜欢允许单例但不强制执行它,所以从不隐藏构造函数和析构函数。这已经说过了我的支持。
我的转折是我不经常使用静态成员函数,除非我想创建一个真正的单例并隐藏构造。我通常的做法是:
template< typename T >
T& singleton( void )
{
static char buffer[sizeof(T)];
static T* single = new(buffer)T;
return *single;
}
Foo& instance = singleton<Foo>();
为什么不使用T的静态实例而不是新的贴图?静态实例提供构造顺序保证,但不提供销毁顺序。大多数对象以相反的构造顺序销毁,但是静态和全局变量。如果你使用静态实例版本,你最终会在主结束后得到神秘/间歇性的段错误等。
这意味着永远不会调用单例析构函数。但是,无论如何都要进行回收,资源将被收回。这有点难以接受,但相信我目前还没有更好的跨平台解决方案。幸运的是,C ++ 0x进行了一些修改,以保证破坏顺序,从而解决这个问题。一旦您的编译器支持新标准,只需升级单例函数即可使用静态实例。
另外,我在实际实现中使用boost来获取对齐的内存而不是普通的字符数组,但是不希望复杂的例子