温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++单例模式与单例类模板

发布时间:2020-07-05 22:00:25 来源:网络 阅读:1190 作者:小溢 栏目:编程语言




1、单例模式


(1)需求的提出:在架构设计时,某些类在整个系统生命周期中最多只能有一个对象存在(Single,Instance)


(2)问题:如何定义一个类,使得这个类最多只能创建一个对象?


要控制类的对象数目,必须对外隐藏构造函数


思路:

@1:将构造函数的访问属性设置为private,将拷贝构造函数,赋值操作符都声明成private的,防止对象的赋值操作,因为这个类的对象只能有一个。

@2:定义instance并初始化为NULL。在类中用static type* instance的方式声明一个静态的变量,按照对这个static修饰的访问规则,之后在类外面进行定义初始化为NULL。

@3:然后在类中在提供一个static的成员函数,用来创建对象的,当我们要创建对象的时候,必然会用调用这个函数,这个函数内部就会去访问instance。 @4:访问instance的值,空值时:创建对象,并用instance进行标记(也就是如果instance为NULL,则直接new一个对象出来将地址赋值给

instance,让instance进行标记),然后返回这个对象。非空值时:直接返回instance标记的对象。这样就保证了这个类只能创建一个对象,这就是单例模式。‘

单例模式的对象在整个系统的运行过程当中是绝对不需要释放的,当系统结束运行时,系统自然就会释放这个对象了。所以单例模式的对象不需要在系统运行的时候,也就是不需要在系统生命周期

还没有结束时进行释放。

例:单例模式


#include <iostream>


using namespace std;


/*

* 单例模式

* why 2016/9/6

*

* 实现单例模式的思路:

*

* @1:将构造函数的访问属性设置为private,将拷贝构造函数,赋值操作符都声明成private的,防止对象的赋值操作,因为这个类的对象只能有一个。

* @2:定义instance并初始化为NULL。在类中用static type* instance的方式声明一个静态的变量,按照对这个static修饰的访问规则,之后在类外面进行定义初始化为NULL。

* @3:然后在类中在提供一个static的成员函数,用来创建对象的,当我们要创建对象的时候,必然会用调用这个函数,这个函数内部就会去访问instance。

* @4:访问instance的值,空值时:创建对象,并用instance进行标记(也就是如果instance为NULL,则直接new一个对象出来将地址赋值给

* instance,让instance进行标记),然后返回这个对象。非空值时:直接返回instance标记的对象。这样就保证了这个类只能创建一个对象,这就是单例模式。‘

*/

/*

* 单例模式的对象在整个系统的运行过程当中是绝对不需要释放的,当系统结束运行时,系统自然就会释放这个对象了。所以单例模式的对象不需要在系统运行的时候,

* 也就是不需要在系统生命周期还没有结束时进行释放。

*/


class SObject

{

private:

SObject() //将构造函数隐藏起来

{

}

SObject(const SObject&); //将拷贝构造函数隐藏起来

SObject& operator = (const SObject&); //将赋值操纵隐藏起来

static SObject *c_instance; //声明一个instance的SObject的指针,将来用来标记创建的对象的,也是指向那个对象的指针。因为是static的,所以需要在外部进行定义,初始化为NULL

public:

static SObject* GetInstance(); //声明,用来创建一个对象的,因为你的构造函数已经为private的,所以我们要自己提供一个。因为static的,所以也要在外部进行定义

void print()

{

cout << "this = " << this << endl;

}

};


SObject* SObject::c_instance = NULL;


SObject* SObject::GetInstance()

{

if (c_instance == NULL)

{

c_instance = new SObject(); //如果c_instance这个标记为空,说明没有对象创建,则创建唯一一个对象

}

return c_instance; //返回这个创建的对象的指针

}


int main(void)

{

SObject* s1 = SObject::GetInstance();

SObject* s2 = SObject::GetInstance();

s1->print(); //this = 0x893d008

s2->print(); //this = 0x893d008 //说明确实只能创建一个对象,因为两个指针指向的都是一个对象

return 0;

}



2、上面的代码实现了单例模式,但是还不是很完美,比如需要定义静态变量c_instance,必须要定义静态成员函数GetIntance(),所以我们可以在完美一下。

解决方案就是:将单例模式相关的代码抽取出来,就是单例模式本身的逻辑模式那部分,不影响类的其他功能,将这部分代码拿出来后开发出单例类模板。当需要单例类时,直接使用单例类模板。

使用方式是,在需要使用单例类模式的类中,用友元关键friend + class + 单例类模板的名字<当前类的名字>,将单例类模板声明为当前类的友元。在单例类模板中实现的是定义静态变量用来

标记对象,和定义静态成员函数来实现判断标记从而决定是否创建新的对象和返回对象的地址。


Singleton英文是单例模式的意思。


3、好的使用单例模式类的例子:


/************************************************单例类模板程序*****************************************/



#ifndef _SINGLETON_H_

#define _SINGLETON_H_


/*

* 单例类模板

* 实现单例模式的逻辑那部分。以后其他的类如果想用单例模式都可以添加将这个单例类模板声明为友元,T是使用该模板的类名,进行实现单例模式

*/


template

< typename T >

class Singleton

{

private:

static T* c_instance;

public:

static T* GetInstance();

};


template 

< typename T >

T* Singleton<T>::c_instance = NULL; //将这个标记首先置位空


template 

< typename T >

T* Singleton<T>::GetInstance()

{

if (c_instance == NULL) //看是否使用单例模式的类已经定义过对象了。

{

c_instance = new T(); //没有定义对象,则创建一个对象//没有定义对象,则创建一个对象

}

return c_instance; //最后返回这个对象的指针,这个标记就记录着这个对象的地址。这样防止对象对此定义。

}


#endif


/*************************************************使用这个单例类模板而实现的单例模式的类*******************************/


#include <iostream>

#include "Singleton.h"


using namespace std;


/*

* SObject使用单例模式,方式是使用的添加单例类模板进行实现的

*

*

*/

//同时必须要将一些跟对象的创建有关的函数弄成private的,隐藏起来。包括:构造函数、拷贝构造函数、赋值操作符重载函数

class SObject

{

private:

friend class Singleton<SObject>; //将使用的单例类模板声明为当前这个类的友元。这样即可达到使用单例类模板。

SObject()

{

}

SObject(const SObject&);

SObject& operator = (const SObject&);

public:

void print()

{

cout << "this = " << this << endl; 

}

};


int main(void)

{

SObject *s1 = Singleton<SObject>::GetInstance();

SObject *s2 = Singleton<SObject>::GetInstance();

SObject *s3 = Singleton<SObject>::GetInstance();

s1->print(); //会发现三个的指针值都是一样,说明都是指向的同一个对象,说明单例模式实现成功,单例模式下的类只能创建一个对象

s2->print();

s3->print();

return 0;

}



向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI