c\c++复习基础要点08--c++单例模式
单例模式有许多种实现方法,在c++中,甚至可以直接用一个全局变量做到这一点,但是这样的代码显得不优雅。使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然能创建相同类的本地实例。
定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态函数获取该实例。
定义:
class CSingleton
{
public:
staticCSingleton * GetInstance()
{
if(m_pInstance==NULL)
m_pInstance = new CSingleton();
return m_pInstance;
}
private:
CSingleton(){};
staticCSingleton * m_pInstance;
};
用户访问唯一实例的函数只有GetInstance()成员函数。因为类的构造函数是私有的。GetInstance()的返回值是当这个函数第一次被调用时创建的实例。所以GetInstance()之后调用都返回同一个实例的指针。
单例类CSingleton的特征:
1. CSingleton有一个指向唯一实例的静态指针m_pInstance,并且是私有的;
2. CSingleton有一个公有的函数,可以获得这个唯一的实例,并且在需要的时候创建实例;
3. CSingleton的构造函数是私有的,这样就不能从别处创建该类的实例。
但是该种实现单例类的方法有一个问题:m_pInstance指向的空间(实例)什么时候释放?
该实例的析构函数什么时候执行?
解决办法:让这个类自己知道在合适的时候把自己释放,或者把释放自己的操作让操作系统在某个适合时候执行。
在程序结束时,系统会自动析构所有的全局变量。事实上,系统也会析构该类的所有静态成员变量。利用这个特征,可以在单例类中定义一个内嵌类的静态成员变量,而这个内嵌类的唯一工作就是在析构函数中去释放单例类的实例。
在CSingleton类中定义一个CGarbo类的静态成员变量:
class CSingleton
{
public:
static CSingleton * GetInstnace()
{
if(m_pInstance==NULL)
m_pInstance = newCSingleton();
return m_pInstance;
}
private:
CSingleton();
static CSingleton * m_pInstance;
class CGarbo
{
public:
~CGarbo()
{
if(CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo;
};
类CGarbo被定义为CSingleton的私有内嵌类,以防该类被在其他地方滥用。
程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。
使用这种方法释放单例对象有以下特征:
在单例类内部定义专有的嵌套类;
在单例类内定义私有的专门用于释放的静态成员;
利用程序在结束时析构全局变量的特性,选择最终的释放时机;
使用单例的代码不需要任何操作,不必关心对象的释放。
另一种实现单例类的方法:定义单例类的实例为GetInstance函数的局部静态变量。
class CSingleton
{
public:
static CSingleton &GetInstance()
{
static CSingleton instance;
return instance;
}
private:
CSingleton(){};
};
使用局部静态变量,非常强大的方法,完全实现了单例的特性,而且代码量更少,也不用担心单例销毁的问题。
但使用此种方法也会出现问题,当如下方法使用单例时问题来了,
Singletonsingleton = Singleton :: GetInstance();
这么做就出现了一个类拷贝的问题,这就违背了单例的特性。产生这个问题原因在于:编译器会为类生成一个默认的构造函数,来支持类的拷贝。
解决方法:禁止类拷贝和类赋值,禁止程序员用这种方式来使用单例
class CSingleton
{
public:
static CSingleton &GetInstance()
{
static CSingleton instance;
return instance;
}
private:
CSingleton(){};
CSingleton(const CSingleton &){};
CSingleton & operate=(constCSingleton &){};
};
关于CSingleton(const Singleton&); 和 CSingleton & operate = (const Singleton&); 函数,需要声明成私用的,并且只声明不实现。这样就可以解决上边的问题,实现单例类。
c\c++复习基础要点08--c++单例模式的更多相关文章
- c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系
1. 引用本身是有指针实现的:引用为只读指针 例子: int d=123; int& e=d; //引用 int * const e=d; //只读指针,e指向d,不可修改e指 ...
- c++复习基础要点02 虚函数与模板 与static inline是否共存
1. 虚函数能否定义为模板函数 当一个类有虚函数时,它一定有一个虚表,用来纪录每个虚函数的实际地址.这也就是说这个虚表的大小是在编译期就确定了的.有多少个虚函数,虚表就纪录几个. ...
- c\c++复习基础要点16----枚举类型
枚举类型: 语法格式: enum 枚举类型名 {变量值列表}; 例如: enum Weekday{sun, mon, tue, wed, thu, fri, set}; 声明了枚举类型后,就可以定义 ...
- iOS系列 基础篇 08 文本与键盘
iOS系列 基础篇 08 文本与键盘 目录: 1. 扯扯犊子 2. TextField 3. TextView 4. 键盘的打开和关闭 5. 打开/关闭键盘的通知 6. 键盘的种类 7. 最后再扯两句 ...
- CORS基础要点:关于dataType、contentType、withCredentials
事实上,面试时我喜欢问跨域,因为多数开发者都知道它并且常用,而我希望能从面试者的回答中知道他在这个问题的深入程度,进一步看看面试者研究问题的思维方式及钻研精神,然而确实难到了很多人,当然这也不是面试通 ...
- 第二十七节:Java基础面向对象-静态,单例模式,继承详情知识点
前言 Java基础面向对象-静态,单例模式,继承详情知识点.静态-static关键字,static变量,静态代码块,代码块(不加静态),对象创建过程,单例模式,继承. 静态-static关键字 // ...
- JUnit单元测试基础要点
JUnit单元测试基础要点 1.JUnit是一种测试代码的框架,测试的目的是:保证代码没错,而不是保证代码正确. 2.测试类一般不要和目标类放在一起,但编译成的class文件是放在一起的. 3.单元测 ...
- JavaScript基础入门08
目录 JavaScript 基础入门08 DOM 介绍 绑定事件 给一组元素绑定事件 节点 节点树 节点类型 选取文档内容 通过id选取元素 通过指定的标签名选取元素 用指定的css类来选取元素 通过 ...
- 068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题——基本数据类型传值
068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题--基本数据类型传值 本文知识点:参数传递问题--基本数据类型传值 说明:因为时间紧张,本人写博 ...
随机推荐
- python面对对象编程------4:类基本的特殊方法__str__,__repr__,__hash__,__new__,__bool__,6大比较方法
一:string相关:__str__(),__repr__(),__format__() str方法更面向人类阅读,print()使用的就是str repr方法更面对python,目标是希望生成一个放 ...
- (@DBRef)spring-data-mongodb
@DBRef用在哪些地方 已知的有 @DBRefprivate Shop product; @DBRefprivate List<Account> accounts; 如果不加@DB ...
- WCF调用问题
1---WCF常用的节点绑定 basicHttpBinding和netTcpBinding 当通过Spring对象注入 如 WCFForOrderService 对象注入 public WCFForO ...
- jQuery入门必须掌握的一些API
jQuery 中文版文档:http://www.css88.com/jqapi-1.9/category/ajax/ jQuery入门,必须掌握以下的API,平时工作中经常会用到.未列出的API,在掌 ...
- Android Studio中新建项目时Your android sdk is out of date or is missing templates的解决办法
在Android Studio中新建项目时出现了以下问题:Your android sdk is out of date or is missing templates. Please ensure ...
- Smokeping如何清空图标数据
先停smokeping服务 service smokeping stop 进去图表数据目录 /opt/smokeping/data /bin/rm -rf ./* 重新加载/opt/smokepi ...
- sql server使用说明
什么是sql server? SqlServer是微软的一款数据库系统产品. 是DBMS中的一种. 当每一个数据库安装到每一台电脑后,都会与计算机名称(有的是IP地址)关联.因为服务器用途的电脑不能经 ...
- Struts2 手动验证
* 首先要从页面中获取对应的标签name属性的值,在动作类action中声明同名的属性,提供get和set方法 * 要继承ActionSupport类或者实现Validateable接口 ...
- 网易JS面试题与Javascript词法作用域说明
调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量).函数参数及Arguments对象都在函数内的作用域中--这意味着它们隐藏了作用域链更上层的任何同名的属性. 2010年9月14日, ...
- Oracle数据库之PL/SQL程序设计基础
PL/SQL程序设计基础 一.PL/SQL块结构 前边我们已经介绍了PL/SQL块的结构,再来回顾一下: DECLARE /* * 声明部分——定义常量.变量.复杂数据类型.游标.用户自定义异常 */ ...