【转】可能继承的C++ Singleton基类

简介: from:http://www.gocalf.com/blog/cpp-singleton.html      单例模式(Singleton Pattern)是设计模式中的一种,它用来保证系统中最多只能存在一个它的实例,其做法是由类自身来创建和持有它的对象实例,把对实例的创建权和管理权都控制在自己手中,以便控制实例数目。

from:http://www.gocalf.com/blog/cpp-singleton.html 

    单例模式(Singleton Pattern)是设计模式中的一种,它用来保证系统中最多只能存在一个它的实例,其做法是由类自身来创建和持有它的对象实例,把对实例的创建权和管理权都控制在自己手中,以便控制实例数目。

    关于如何在C++中实现单例模式的讨论已经太多了,我只是简单介绍一下可以继承的单例类。

    首先介绍一下通常所见的单例类的写法,不妨设这个类叫做Singleton。

Singleton.h:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef _SINGLETON_H_
#define _SINGLETON_H_

#include <memory>

class Singleton
{
public :
    static Singleton & GetInstance ( ) ;

private :
    Singleton ( ) ;
    ~Singleton ( ) ;

    // Use auto_ptr to make sure that the allocated memory for instance
    // will be released when program exits (after main() ends).
    static std :: auto_ptr <singleton > s_instance ;
    friend class std :: auto_ptr <singleton > ;

    Singleton ( const Singleton & ) ;
    Singleton & operator = ( const Singleton & ) ;
} ;

#endif

Singleton.cpp:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "Singleton.h"
#include <iostream>
#include <boost thread.hpp="">

using namespace std ;
using namespace boost ;

auto_ptr <singleton > Singleton :: s_instance ;

Singleton :: Singleton ( )
{
    cout << "Construct Singleton" << endl ;
}

Singleton ::~Singleton ( )
{
    cout << "Destruct Singleton" << endl ;
}

Singleton & Singleton :: GetInstance ( )
{
    static mutex s_mutex ;
    if (s_instance. get ( ) == NULL )
    {
        mutex :: scoped_lock lock (s_mutex ) ;
        if (s_instance. get ( ) == NULL )
        {
            s_instance. reset ( new Singleton ( ) ) ;
        }
        // 'lock' will be destructed now. 's_mutex' will be unlocked.
    }
    return *s_instance ;
}

      这个类写的也不完美啦,比如双重判定也会有失效的时候,不过凑合用吧,哈哈。不过话说boost库里也有singleton,我为什么要自己写个呢,无奈地飘过。

废话不多说了,上面的单例类基本上解决了多线程安全问题、实例内存自动释放问题,算是一段可以使用的程序。不过如果系统中有大量单例类(这时候也得好好考虑一下design有没有问题),每个都要这么写一番岂不是很麻烦?要是可以写一个单例基类,以后再创造单例类的时候直接继承一下多方便啊。不过很明显的问题就在那个static对象指针,这个用来保存唯一实例的静态变量如果定义在基类里面,那所有的子类都只能用这同一个变量来保存它们各自的实例了,社会主义国家总得让每个子类都过上温饱生活吧!

      以前的时候我还真不知道该怎么解决这个问题,但05年用了WTL(Windows Template Library)之后,我才意识到模板类可以帮助我(话说我真的是自己想到的,虽然现在搜一下能搜到一大堆)。这里要用的还不是普通的模板类,而是像ATL、WTL里面那样把要定义的类自身放入模板参数中,形如class MyClass : public Base<myclass> { };。这样做有很多优点啦,最显著的比如不需要虚表(节省内存哦)、多态函数的调用在编译时就确定了(既加快了运行速度,也有利于编译器对代码进行优化)。

      不妨把这个单例基类叫做ISingleton吧,看起来好像是个interface呢。代码如下:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef _ISingleton_H_
#define _ISingleton_H_

#include <memory>
#include <boost thread.hpp="">

template < typename t = "" >
class ISingleton
{
public :
    static T & GetInstance ( )
    {
        static boost :: mutex s_mutex ;
        if (s_instance. get ( ) == NULL )
        {
            boost :: mutex :: scoped_lock lock (s_mutex ) ;
            if (s_instance. get ( ) == NULL )
            {
                s_instance. reset ( new T ( ) ) ;
            }
            // 'lock' will be destructed now. 's_mutex' will be unlocked.
        }
        return *s_instance ;
    }

protected :
    ISingleton ( ) { }
    ~ISingleton ( ) { }

    // Use auto_ptr to make sure that the allocated memory for instance
    // will be released when program exits (after main() ends).
    static std :: auto_ptr <t > s_instance ;

private :
    ISingleton ( const Singleton & ) ;
    ISingleton & operator = ( const ISingleton & ) ;
} ;

template < typename t = "" >
std :: auto_ptr <t > ISingleton <t > :: s_instance ;

#endif

      要利用ISingleton创建一个自己的单例类,比如MySingleton,可以使用如下的代码:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "Singleton.h"
#include "ISingleton.h"
#include <iostream>

using namespace std ;

class MySingleton : public ISingleton <mysingleton >
{
public :
    // blah blah

private :
    MySingleton ( )
    {
        cout << "Construct MySingleton" << endl ;
    }

    ~MySingleton ( )
    {
        cout << "Destruct MySingleton" << endl ;
    }

    friend ISingleton <mysingleton > ;
    friend class auto_ptr <mysingleton > ;

    MySingleton ( const MySingleton & ) ;
    MySingleton & operator = ( const MySingleton & ) ;
} ;

      最最重要的,千万不要忘了把MySingleton的构造和析构函数弄成private的,还要添加两个友元。有人说ISingleton和MySingleton的析构函数都要加virtual,我倒是觉得没有必要呢,你说呢?另外要注意,MySingleton不能被继承哦。

 

目录
相关文章
|
8天前
|
Java C++
C++的学习之路:21、继承(2)
C++的学习之路:21、继承(2)
16 0
|
2月前
|
C++
8. C++继承
8. C++继承
26 0
|
2月前
|
安全 程序员 编译器
C++之继承
C++之继承
|
2月前
|
设计模式 存储 uml
C++ 设计模式实战:外观模式和访问者模式的结合使用,派生类访问基类的私有子系统
C++ 设计模式实战:外观模式和访问者模式的结合使用,派生类访问基类的私有子系统
29 1
|
8天前
|
安全 编译器 程序员
c++的学习之路:20、继承(1)
c++的学习之路:20、继承(1)
26 0
|
2月前
|
安全 Java 编译器
C++:继承
C++:继承
32 0
|
2月前
|
安全 Java 程序员
【C++练级之路】【Lv.12】继承(你真的了解菱形虚拟继承吗?)
【C++练级之路】【Lv.12】继承(你真的了解菱形虚拟继承吗?)
|
2月前
|
安全 Java 编译器
C++:继承与派生
C++:继承与派生
|
2天前
|
安全 Java 程序员
【C++笔记】从零开始认识继承
在编程中,继承是C++的核心特性,它允许类复用和扩展已有功能。继承自一个基类的派生类可以拥有基类的属性和方法,同时添加自己的特性。继承的起源是为了解决代码重复,提高模块化和可维护性。继承关系中的类形成层次结构,基类定义共性,派生类则根据需求添加特有功能。在继承时,需要注意成员函数的隐藏、作用域以及默认成员函数(的处理。此外,继承不支持友元关系的继承,静态成员在整个继承体系中是唯一的。虽然多继承和菱形继承可以提供复杂的设计,但它们可能导致二义性、数据冗余和性能问题,因此在实际编程中应谨慎使用。
5 1
【C++笔记】从零开始认识继承
|
5天前
|
设计模式 编译器 数据安全/隐私保护
C++ 多级继承与多重继承:代码组织与灵活性的平衡
C++的多级和多重继承允许类从多个基类继承,促进代码重用和组织。优点包括代码效率和灵活性,但复杂性、菱形继承问题(导致命名冲突和歧义)以及对基类修改的脆弱性是潜在缺点。建议使用接口继承或组合来避免菱形继承。访问控制规则遵循公有、私有和受保护继承的原则。在使用这些继承形式时,需谨慎权衡优缺点。
16 1