2014-11-20 157 views
-1

我在这里做了一些关于这个主题的关于stackoverflow的研究,但是我没有从我可以学习的地方找到一个单独的答案,singleton类是如何工作的。我已经知道一个单例类只能有一个实例。有人可以解释我- 或者链接我一个教程 -如何创建最基本的单例类,并逐行告诉我为什么/它是如何工作的? 我有麻烦的是,我抬头的答案和一些教程并没有真正解释为什么我应该声明某个变量或函数为静态,指针等如何在C++中创建一个简单的单例类?

+1

请参阅http://stackoverflow.com/questions/1008019/c-singleton-design-pattern/1008289#1008289 – statueuphemism 2014-11-20 20:40:07

+0

然后,您应该首先了解静态指针和指针! – Venkatesh 2014-11-20 20:40:11

+0

在Singletons上找不到任何有用的东西?这很难相信... – Borgleader 2014-11-20 20:42:16

回答

2

Discalimer

一般一个应尽量避免使用单身和/或全局对象。应该明确传递函数所需的对象。这使得在并行代码时通过传递模拟对象,调试和减少争用来轻松测试函数。例如,我的应用程序中唯一的全局对象是记录器(类似于标准I/O流)和线程特定的事件循环引擎。

使用单例或全局对象的唯一原因是为了避免在所有函数调用中传递它的麻烦。例如。您不希望通过每次调用传递一个记录器对象,但不需要创建许多本地或成员记录器对象以节省空间和时间。


方法1

最基本的单是在运行过程中,在动态初始化阶段初始化的全局对象,如:

// singleton.h 
class Singleton { /*...*/ }; 
extern Singleton singleton; 

// singleton.cc 
#include "singleton.h" 
extern Singleton singleton(/*...*/); 

好处:

  • 在输入main之前初始化。
  • 线程安全初始化。
  • 非侵入性,不要求该类是“单身人士”。它是对象singleton什么是单身人士,而不是班级本身。

缺点:

  • 一些构造函数的参数main之前可能无法使用。

这样的对象也可以main之前使用的通过确保它被使用Schwarz Counter第一访问之前初始化(同样的方法std::cout和朋友得到初始化)进入。


方法2

另一种选择是有一个全球性的指针的对象。该指针在main的早期初始化,并在main堆栈上创建一个对象。

E.g.:

// singleton.h 
class Singleton { /*...*/ }; 
extern Singleton* singleton; 

// main.cc 
int main() { 
    Singleton the_singleton(/*...*/); 
    singleton = &the_singleton; 

    // at main end 
    singleton = nullptr; 
} 

益处的那些方法的1


方法3

函数作用域静态在C++ 11(GCC这样做之前C++ 11) object:

// singleton.h 
class Singleton { /*...*/ }; 
Singleton& get_singleton(); 

// singleton.cc 
Singleton& get_singleton() { 
    static Singleton singleton; 
    return singleton; 
} 

Benefit其和缺点的那些方法1.


方法4

双检锁定单的。 Not necessary in C++11,作为功能范围静态为您执行线程安全初始化。

+0

我的理解是应该只有一个实例。你的答案如何证明这个概念? – 2014-11-20 20:49:24

+1

@ThomasMatthews从流程的角度来看,单一类的对象可以有多个实例。如果组件需要访问同一个对象,他们通过相同的名称访问它,例如:'singleton.foo()','singleton-> foo()','get_singleton()。foo()'。你可以强制规定这个类只有一个对象,但根据我的经验,这很少是必需的。 – 2014-11-20 21:04:01

+0

谢谢你的一切!我正在尝试创建一个游戏,并且我想创建一个加载并绘制所​​有动画精灵(图像)的类。现在,如果我创建了一个简单的类,没有任何东西阻止我(或任何人)创建该类的多个实例,但我只需要一个对象来处理所有的绘图和加载。我从书中得到了它的代码,但我不明白它是如何工作的。 – 2014-11-20 21:06:20

2

勺子男孩:不要尝试和单独的班级。这是 不可能的。 不好的做法。相反......只是尝试意识到事实。

Neo:什么道理?

勺子男孩:没有单身。

Neo:没有单身?

勺子男孩:然后你会看到,它不是只限于一个实例的类,它只是你需要一个实例。

我想说的是:作为一个类的作者,永远不要强迫这个类是一个单身人士。仅仅因为您认为系统今天只需要一个Logger对象,并不意味着明天您可能不需要两个(例如一个用于Windows应用程序事件日志,一个用于系统事件日志)。

认为你的thread_pool类应该是单身?那么,我需要一个公平的线程池和一个我的应用程序中的LIFO线程池。

如果您创建N个Agent对象,他们都需要共享一个Logger对象,不写Logger为单 - 而使用这样的:

// agent.h 
class Agent { 
    ... 
    private: 
     Logger& GetLogger(); 
} 

// agent.cpp 
Logger& Agent::GetLogger() { 
    static Logger TheOne; 
    return The One; 
} 

毕竟,这是Agent需要Logger是单身人士 - 而不是Logger本身!

相关问题