C ++中类的全局实例

时间:2008-11-18 04:05:26

标签: c++ singleton

正如标题所说。我如何创建一个全局可用的类的实例(例如,我有一个打印的仿函数,我希望有一个这样的全局实例(虽然可以创建更多))。

7 个答案:

答案 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正是您要找的。

答案 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的以下博客。

  1. Singletons are Pathological Liars

  2. Root Cause of Singletons

  3. Where Have All the Singletons Gone?

答案 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来获取对齐的内存而不是普通的字符数组,但是不希望复杂的例子