11

正如标题所说。我将如何创建一个全局可用的类的实例(例如,我有一个用于打印的函子,我想拥有一个全局实例(尽管有可能创建更多))。

4

7 回答 7

20

使用通常的模式制作单例对象的所有努力并没有解决您问题的第二部分 - 如果需要,能够制作更多。单例“模式”的限制性非常强,只不过是另一个名称的全局变量。

// myclass.h

class MyClass {
public:
    MyClass();
    void foo();
    // ...
};

extern MyClass g_MyClassInstance;

// myclass.cpp

MyClass g_MyClassInstance;

MyClass::MyClass()
{
    // ...
}

现在,在任何其他模块中只需像往常一样包含myclass.h和使用。g_MyClassInstance如果你需要做更多,有一个构造函数可供你调用。

于 2008-11-18T04:18:58.927 回答
5

First off the fact that you want global variables is a 'code smell' (as Per Martin Fowler).

But to achieve the affect you want you can use a variation of the Singleton.
Use static function variables. This means that variable is not created until used (this gives you lazy evaluation) and all the variables will be destroyed in the reverse order of creation (so this guarantees the destructor will be used).

class MyVar
{
    public:
        static MyVar& getGlobal1()
        {
            static MyVar  global1;
            return global1;
        }
        static MyVar& getGlobal2()
        {
            static MyVar  global2;
            return global2;
        }
        // .. etc
}
于 2008-11-18T06:22:06.367 回答
1

作为对单例模式的轻微修改,如果您确实希望允许创建更多具有不同生命周期的实例,只需将 ctors、dtor 和 operator= 设为 public。这样就可以通过 GetInstance 获得单个全局实例,但也可以在堆或堆栈上声明相同类型的其他变量。

然而,基本思想是单例模式。

于 2008-11-18T04:18:26.227 回答
1

单例模式使用起来很不错,但它也有自己的缺点。在使用单例之前,请阅读 Miško Hevery 的以下博客。

  1. 单身人士是病态的骗子

  2. 单身人士的根本原因

  3. 所有单身人士都去哪儿了?

于 2008-11-18T05:54:33.443 回答
0

Singleton 模式是您正在寻找的。

于 2008-11-18T04:08:35.903 回答
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();
}

有关John Vlissides(来自 GoF 名声)的分析,请参见此处的主题 IV 。

于 2008-11-18T05:30:29.967 回答
0

I prefer to allow a singleton but not enforce it so in never hide the constructors and destructors. That had already been said just giving my support.

My twist is that I don't use often use a static member function unless I want to create a true singleton and hide the constr. My usual approach is this:

template< typename T >
T& singleton( void )
{
   static char buffer[sizeof(T)];
   static T* single = new(buffer)T;
   return *single;
}

Foo& instance = singleton<Foo>();

为什么不使用 T 的静态实例而不是放置 new?静态实例提供构造顺序保证,但不提供破坏顺序。大多数对象以相反的构造顺序被销毁,但静态和全局变量。如果您使用静态实例版本,您最终会在 main 结束后得到神秘/间歇性的段错误等。

这意味着永远不会调用单例析构函数。但是,无论如何,进程都会下降,资源将被回收。这有点难以习惯,但相信我,目前没有更好的跨平台解决方案。幸运的是,C++0x 进行了更改以保证销毁顺序,这将解决这个问题。一旦您的编译器支持新标准,只需升级单例函数以使用静态实例。

另外,我在实际实现中使用 boost 来获得对齐的内存而不是普通字符数组,但不想使示例复杂化

于 2008-11-18T07:29:31.583 回答