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

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不能被继承哦。

 

时间: 2024-09-24 15:47:20

【转】可能继承的C++ Singleton基类的相关文章

可以继承的C++ Singleton基类

单例模式(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

派生类与派生类对象对基类成员的访问

区分"派生类对象"和"派生类"对基类成员的访问权限.    "派生类对象"对基类成员的访问权限:      (1)对于公有继承,只有基类的公有成员可以被"派生类对象"访问,其他(保护和私有)成员不能被访问.      (2)对于私有继承和保护继承,基类中所有成员都不能被"派生类对象"访问.    "派生类"对基类中成员的访问权限:     (1)对于公有继承,基类中的公有成员和保护成

PHP中用接口、抽象类、普通基类实现“面向接口编程”与“耦合方法”简述

复制代码 代码如下: <?php /* 边学边做的,为方便自己翻阅而发布,更为得到高人指点而发布,欢迎高手指点...... [提示]本例通过测试无误 [情景设计] 模拟计算机主板IDE接口,比如:主板可以存取的储存器常常有光驱.硬盘.闪存等等, 为了方便,有必要对这些不同的储存器设定同一的接口. 本例还假设一种前所未有的.存取方式与众不同的外星储存器也要加到主板上进行存取, 于是需要采用耦合的设计模式. [本例主要讲述] 1.通过接口.抽象类.一般类继承三种方式达到所谓的"接口"

ASP.NET Atlas简单控件介绍之两个基类

asp.net|控件 ASP.NET Atlas中引入了客户端控件的概念,用面向对象思想将客户端JavaScript将要操作的DOM元素封装起来,带来了更清晰的代码模型以及更好的可复用性(不足之处是效率有所降低).Atlas的客户端控件是连接JavaScript与DOM元素的桥梁,我们应该尽可能的使用客户端控件与DOM元素打交道,也就是以Atlas的方法来编写我们的程序.同时,Atlas对JavaScript面向对象方面的强大扩展(请参考:ASP.NET Atlas对JavaScript的扩展)

为数据访问层编写一个基类

访问|数据 在编写数据访问层代码时,总要一边又一边的重复编写:读数据库连接字符串,建立数据库连接对象,打开连接,创建Command对象,创建数据适配器,创建数据集,填充数据集,关闭连接.这种重复的代码写一两次到还行,写多了就免不了有一些烦了. 在总结以前的代码以后,决定重构数据方法层的代码.数据访问层无非进行两种操作:查询返回DataTable,进行插入.更新.删除等无返回值的操作.只要增加一个数据访问层基类包含这些繁琐的代码,其余的数据访问层代码继承数据访问层基类,在调用基类函数时给出存储过程

实例讲解C++编程中的虚函数与虚基类_C 语言

虚函数① #include "stdafx.h" #include <iostream> using namespace std; class B0//基类B0声明 { public: void display(){cout<<"B0::display()"<<endl;}//公有成员函数 }; class B1: public B0//公有派生类B1声明 { public: void display(){cout<<

iOS Foundation 框架基类

 iOS Foundation 框架基类 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 基类 Title Topic Date NSObject Class Reference Data Ty

请问:C#中 虚基类 等于 抽象类吗?

问题描述 请问大家:(1)在C#中有虚基类吗?(2)如果有和抽象类有什么区别?在项目开发中主要应用在哪些方面?(3)还有虚方法和抽象方法有什么区别? 解决方案 解决方案二:你可以去www.langsin.com,找抽像类的视频,那里面有介绍解决方案三:C#中没有多继承,所以也就没有虚基类了.虚表示可以重写,运行时绑定,抽象表示只有定义没有实现,含义不一样.解决方案四:没有虚基类虚方法可以由子类来重写,也可以不重写.抽象方法必须由子类来重写.解决方案五:谢谢了解决方案六:C#只允许单继承,没有虚基

C# 类中隐藏基类方法和Partial

原文:C# 类中隐藏基类方法和Partial 今天对于.NET开发人员来说最开心的事情莫过于微软搞开源了,这觉得是给搞.NET开发的长脸.虽然我是一个初学者,这无疑给我极大的学习动力.Fighting!!! 当一个类从父类继承了一个成员时,也就继承了它的执行代码,如果成员时虚拟的,我们可以用override重写这段执行代码.但无论他是否是虚拟的,都可以通过new 关键字来隐藏它.例如: public class BaseClass { public void DoSomething() { //