单例模式特点:
-
整个工程只能产生一个对象
-
在整个工程的任何地方都能使用到这个对象
禁止拷贝构造即等号赋值
在单例模式中,不允许对象进行拷贝构造以及等号赋值,可通过以下来禁止掉,在C11新标准引入了 =delete,如下:
#include<iostream> using namespace std; #define SEQ_INIT_SIZE 10 class SeqList { int data[SEQ_INIT_SIZE]; int maxsize; int cursize; SeqList(const SeqList& src); //设计成私有的防止外界调用拷贝,只有声明没有函数体。 // 一方面告诉了系统已经有拷贝构造,无需在提供默认拷贝构造 //另一方面没有函数体,即使存在友元,也无法进行拷贝构造 //C11标志中 ,提供了明确的去掉函数的方法:=delete;例: //SeqList(const SeqList& src)=delete;即阻碍对象进行拷贝构造 //例:去掉赋值函数 SeqList& operator=(const SeqList& src) = delete; public: SeqList() :maxsize(SEQ_INIT_SIZE), cursize(0) {} /* SeqList& operator=(const SeqList& src) //拷贝构造,被禁止 :maxsize(SEQ_INIT_SIZE), cursize(0) { memcpy(data, src.data, sizeof(data)); } SeSeqList& operator=(const SeqList& src)//赋值方法,被禁止 { if (this!=&src) { maxsize = src.maxsize; cursize = src.cursize; memcpy(data, src.data, sizeof(data)); } return *this; } */ ~SeqList(){} friend int main();//将main函数设计成友元函数 }; int main() { SeqList seqa; //SeqList seqb(seqa);//错误,已经声明无拷贝构造 SeqList seqc; //seqc = seqb; //错误,已经声明无等号赋值 }
单例模式应用:
抽象太阳,仅有一个,哪里都能用
方法一:指针法:懒汉模式,用时构建
#include<iostream>; using namespace std; #include<mutex> class Sun { public: static Sun* get_Sun()//设计成静态,使可以通过类作用域访问,此函数用来判断是否可以去访问在私有中的构造函数,设计成指针形式可获得该成员的地址 { if (NULL==_only_sun)//双重if判断 { _lock->lock()//用锁来控制在多线程的情况中只有一个线程能构造 if (_only_sun == NULL)//如果为空,说明还未构造过,可访问构造 { _only_sun = new Sun();//在堆上构造,将地址给回来 } _lock->unlock();//解锁 } return _only_sun;//如果不为空,直接返回当前地址就可以 } private: Sun()//构造 { } int _fire; static mutex _lock;//定义一个锁子静态变量 static Sun* _only_sun;//定义静态成员 }; Sun* Sun::_only_sun = NULL;//初始化静态成员 int main() { Sun::get_Sun;//通过作用于访问 } mutex* Sun::_lock=new mutex();//初始化锁子,注:锁子b拷贝构造,赋值
方法二:饥汉模式,先构建
class Object { private: int value; static Object instance; private: Object(int x=0) :value(x) {} Object(const Object& obj) = delete; Object& operator=(const Object& obj) = delete; public: static Object& GetInstance()//还可以以指针返回地址,不能以值返回,因为没有拷贝构造函数 { return instance; } }; Object Object::instance(10);//进入主函数之前便构建出来,不执行构造函数 int main() { Object& obja = Object::GetInstance(); Object& objb = obja.GetInstance(); }