探测器 C++ Singleton(辛格尔顿)
刚开始学习的人可能误, 误以为所有的成员变量和成员方法用于 static , 就是单例模式了:
{
public:
/* static method */
private:
static Singleton m_data; //static data member 在类中声明。在类外定义
};
Singleton Singleton::m_data;
你的类就 必须 得要有构造函数, 并确保初始化顺序).
第二, 最严重的问题, 失去了面对对象的重要特性 -- "多态", 静态成员方法不可能是 virtual 的(补充一点,静态成员方法也不可能是 const 的). Singleton类的子类没法享受 "多态" 带来的便利.
二、饿汉模式
饿汉模式 是指单例实例在程序执行时被马上执行初始化:
{
public:
static Singleton& getInstance()
{
return m_data;
}
private:
static Singleton m_data; //static data member 在类中声明。在类外定义
Singleton(){}
~Singleton(){}
};
Singleton Singleton::m_data;
这就出问题了. 由于 BSingleton m_data 静态对象可能先 ASingleton 一步调用初始化构造函数, 结果 ASingleton::getInstance() 返回的就是一个未初始化的内存区域, 程序还没跑就直接崩掉。
恩。这仅仅是理论分析的结果。以下给出一个简单的样例说明一下问题所在吧!
{
public:
static ASingleton* getInstance()
{
return &m_data;
}
void do_something()
{
cout<<"ASingleton do_something!"<<endl;
}
protected:
static ASingleton m_data; //static data member 在类中声明。在类外定义
ASingleton();
~ASingleton() {}
};
class BSingleton
{
public:
static BSingleton* getInstance()
{
return &m_data;
}
void do_something()
{
cout<<"BSingleton do_something!"<<endl;
}
protected:
static BSingleton m_data; //static data member 在类中声明,在类外定义
BSingleton();
~BSingleton() {}
};
ASingleton ASingleton::m_data;
BSingleton BSingleton::m_data;
ASingleton::ASingleton()
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton::BSingleton()
{
cout<<"BSingleton constructor!"<<endl;
}
{
;
}
BSingleton do_something!
BSingleton constructor!
BSingleton BSingleton::m_data;
这两个定义式,那么就会依次调用 ASingleton 的构造函数 和 BSingleton 的构造函数进行初始化。
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton 类中存在着其声明,那么还是能够调用到其 do_something 方法的。
ASingleton 单例对象 m_data 也就初始化完毕了。
BSingleton 的构造函数了。
//BSingleton BSingleton::m_data;
//改动成:
BSingleton BSingleton::m_data;
ASingleton ASingleton::m_data;
BSingleton constructor!
BSingleton do_something!
实现单例模式的致命缺点。
{
public:
static Singleton* getInstance()
{
if(! m_data) m_data = new Singleton();
return m_data;
}
private:
static Singleton* m_data; //static data member 在类中声明,在类外定义
Singleton(){}
~Singleton(){}
};
Singleton* Singleton::m_data = nullptr;
getInstance() 仅仅在第一次被调用时为 m_data 分配内存并初始化. 嗯, 看上去全部的问题都攻克了, 初始化顺序有保证, 多态也没问题.
例如说,有两个多线程同一时候进入到这种方法中,同一时候运行 if 语句的推断,那么就会出现两次两次初始化静态实例变量的情况。
{
// ... release resource
if (nullptr != m_data)
{
delete m_data;
m_data = nullptr;
}
}
public:
static Singleton& getInstance() {
static Singleton theSingleton;
return theSingleton;
}
/* more (non-static) functions here */
private:
Singleton(); // ctor hidden
Singleton(Singleton const&); // copy ctor hidden
Singleton& operator=(Singleton const&); //
assign op. hidden
~Singleton(); // dtor hidden
};
const BSingleton& b = BSingleton::getInstance();
static ASingleton theSingleton;
return theSingleton;
}
BSingleton& BSingleton::getInstance() {
const ASingleton & b = ASingleton::getInstance();
static BSingleton theSingleton;
return theSingleton;
}
Singleton 类, 当中 ASingleton BSingleton 的析构函数调用了CSingleton 实例的成员函数,
程序退出时, CSingleton 的析构函数 将首先被调用, 导致实例无效, 那么兴许 ASingleton BSingleton 的析构都将失败,
导致程序异常退出.
{
static bool constructed = false;
static uninitialized Singleton instance_;
if (!constructed) {
constructed = true;
new(&s) Singleton; //construct it
}
return instance_;
}
解决问题的办法是为指示类是否已经实例化的变量提供一个相互排斥锁 (尽管这样会减少效率).
{
Lock();
//锁自己实现 static
Singleton instance_;
UnLock();
return instance_;
}
五、终极方案
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
protected:
struct Object_Creator
{
Object_Creator()
{
Singleton::getInstance();
}
};
static Object_Creator _object_creator;
Singleton() {}
~Singleton() {}
};
Singleton::Object_Creator Singleton::_object_creator;
在前面的方案中:饿汉模式中,使用到了类静态成员变量,可是遇到了初始化顺序的问题; 懒汉模式中。使用到了静态局部变量,可是存在着线程安全等问题。
方法。
这样就会调用到 Singleton::getInstance()
方法初始化单例对象。那么自然 Singleton 的构造函数也就运行了。
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
protected:
struct Object_Creator
{
Object_Creator()
{
cout<<"Object_Creator constructor"<<endl;
Singleton::getInstance();
}
};
static Object_Creator _object_creator;
Singleton() {cout<<"Singleton constructor"<<endl;}
~Singleton() {}
};
Singleton::Object_Creator Singleton::_object_creator;
Singleton constructor
{
public:
static ASingleton* getInstance()
{
static ASingleton instance;
return &instance;
}
void do_something()
{
cout<<"ASingleton do_something!"<<endl;
}
protected:
struct Object_Creator
{
Object_Creator()
{
ASingleton::getInstance();
}
};
static Object_Creator _object_creator;
ASingleton();
~ASingleton() {}
};
class BSingleton
{
public:
static BSingleton* getInstance()
{
static BSingleton instance;
return &instance;
}
void do_something()
{
cout<<"BSingleton do_something!"<<endl;
}
protected:
struct Object_Creator
{
Object_Creator()
{
BSingleton::getInstance();
}
};
static Object_Creator _object_creator;
BSingleton();
~BSingleton() {}
};
ASingleton::Object_Creator ASingleton::_object_creator;
BSingleton::Object_Creator BSingleton::_object_creator;
ASingleton::ASingleton()
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton::BSingleton()
{
cout<<"BSingleton constructor!"<<endl;
}
BSingleton constructor!
BSingleton do_something!
class Singleton
{
struct object_creator
{
object_creator()
{
Singleton<T>::instance();
}
inline void do_nothing() const {}
};
static object_creator create_object;
public:
typedef T object_type;
static T& instance()
{
static T obj;
//这个do_nothing是确保create_object构造函数被调用
//这跟模板的编译有关
create_object.do_nothing();
return obj;
}
};
template <typename T> typename Singleton<T>::object_creator
Singleton<T>::create_object;
class QMManager
{
protected:
QMManager() {}
~QMManager() {}
friend class Singleton<QMManager>;
public:
void do_something() {};
};
int main()
{
Singleton<QMManager>::instance().do_something();
;
}
boost 通过加入一个类似 proxy-class 的方式,实现了单例模式,可是显然添加了复杂性,在实际应用中应该依据实际情况採用适当的实现方案。
探测器 C++ Singleton(辛格尔顿)的更多相关文章
- 亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本
称号:设计一个类.我们只能产生这个类的一个实例.(来自<剑指Offer>) 解析:仅仅能生产一个实例的类是实现Singleton(单例)模式的类型.因为设计模式在面向对象程序设计中起着举足 ...
- 设计模式——辛格尔顿(Singleton)
要想正确理解设计模式,首先必须明白它是为了解决什么问题而提出来的. 设计模式学习笔记 --Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 单例模式属于设计模式 ...
- Swift辛格尔顿设计模式(SINGLETON)
本文已更新为2.0语法,具体查看:一叶单例模式 一.意图 保证一个类公有一个实例.并提供一个訪问它的全局訪问点. 二.使用场景 1.使用场景 当类仅仅能有一个实例并且客户能够从一个众所周知的訪问点訪问 ...
- 【从cocos2d-x学习设计模式】第一阶段:辛格尔顿
设计模式,它总结了前辈在许多方案重用代码.它是一个想法. 因为我们爱cocos2d-x,然后我们从去cocos2d-x在设计模式中,右一起学习!本篇解释未来辛格尔顿. 提cocos2d-x中间Dire ...
- 辛格尔顿和Android
辛格尔顿(Singleton) .singleton.h,定义类的基本成员及接口 #ifndef SINGLETON_H_INCLUDE #define SINGLETON_H_INCLUDE cla ...
- 23种设计模式--单例模式-Singleton
一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
- PHP设计模式(四)单例模式(Singleton For PHP)
今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...
- The Java Enum: A Singleton Pattern [reproduced]
The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...
随机推荐
- Sql Server远程查询db 表中的数据,以本地
step 1: sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'Ad Hoc Distributed Queri ...
- clientIDMode的应用
以前我们可以通过ClientID在JavaScript脚本中服务器端控件.比如: document.getElementById("<%=控件.ClientID %>" ...
- linux挂载U盘,及乱码问题解决
1. 首先使用切换到root用户. 2. 使用fdisk -l命令查看磁盘信息,找到u盘(能够依据显示的大小确定) 3. 在/mnt下创建挂载点,比如创建usb目录:mkdir /mnt/usb 4. ...
- c++ primer 函数传值1
不看c++ primer 永远不知道自己基础有多差 函数的參数传值一般有两种方式:值传递,引用传递. 值传递有以下两种形式: void func( int a ) { // } void func1 ...
- C++11:强类型枚举(enum)
// C++11之前的enum类型是继承C的,不温不火: // C++11对enum动刀了,加强了类型检查,推出强类型enum类型,眼前一亮 // 使用过QT 的都知道,早就应该这么做了,用的非常爽! ...
- Spring3 MVC请求参数获取的几种场景
访问/aaa/bbb所对应的@Controller @RequestMapping("/aaa")//类级别,可以不需要,如果要了,下面所有的请求路径前都需要加入/aaa publ ...
- HDU 2017 一系列统计数据
一系列统计数据 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- Peter's Hobby
主题链接 题意: 题意比較麻烦.. .n天,给出每天的叶子的一种状态(Dry , Dryish , Damp and Soggy),最有可能出现的天气序列(Sunny, Cloudy and Rain ...
- 【C++探索之旅】开宗明义+第一部分第一课:什么是C++?
内容简介 1.课程大纲 2.第一部分第一课:什么是C++? 3.第一部分第二课预告:C++编程的必要软件 开宗明义 亲爱的读者,您是否对C++感兴趣,但是C++看起来很难,或者别人对你说C++挺难的, ...
- yum 安装时错误 Errno 14 Couldn't resolve host 解决办法(转)
在安装mlocate的时候发现一直报错,错误内容大致如下 Downloading Packages:http://mirrors.163.com/centos/6.5/os/i386/Packages ...