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 参数传递问题--基本数据类型传值 本文知识点:参数传递问题--基本数据类型传值 说明:因为时间紧张,本人写博 ...
随机推荐
- JAVAEE学习
首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA).J2SE,Java 2 Platform Standard Edition,我们经常说到的JDK,就主要指的这个,它 ...
- uploadify在asp.net中的试用小结
花了差不多一下午的时间,总算把uploadify插件运行起来,在此对自己遇到的问题以及过程做一个小结. 一.使用步骤 1.在官网下载最新的插件包,并将包解压. 2.新建asp.net web项目,将解 ...
- JAVA泛型那些事儿
本篇内容源于本人一个好友sgpro提供的java学习例子,现拿出来给大家分享. 此例子非常直观的通过代码讲解了java泛型的用法和好处,是笔者一直珍藏的最好的泛型学习笔记. 一.面向过程的时代 我们先 ...
- MySQL利用binlog来恢复数据库
1.根据binlog解析出所有ring数据库的所有sql [mysql@localhost ]$ mysqlbinlog --no-defaults --database=ring --start-d ...
- JavaScript 客户端JavaScript之cookie和客户端持久性
Document对象都有一个cookie属性,它使得JavaScript代码能够在用户的硬盘上持久地存储数据, 并且能够获取以这种方式存储的数据.客户端持久性是赋予WEB应用程序记忆力的一种简单方法. ...
- 你好,C++(28)用空间换时间 5.2 内联函数 5.3 重载函数
5.2 内联函数 通过5.1节的学习我们知道,系统为了实现函数调用会做很多额外的幕后工作:保存现场.对参数进行赋值.恢复现场等等.如果函数在程序内被多次调用,且其本身比较短小,可以很快执行完毕,那么 ...
- image控件读取数据库二进制图片
DataGridShowImage.aspx <%@ Page language="c#" debug="true" Codebehind=" ...
- phpcms V9 联动菜单的调用
/*********************************** 通过id获取显示联动菜单的 顶级父类的名称* @param $linkageid 联动菜单id* @param $keyi ...
- tcpdump使用和TCP/IP包分析
关于tcpdump如何抓包,本文不再总结,可以查看 tcpdump的官方地址查看http://www.tcpdump.org 本文重点记录两个部分: 第一部分:tcpdump所抓包 ...
- php __clone实现
<?php class Account { public $balance; public function __construct($balance) { $this->balance ...