目录
一、特殊类设计
二、类型转换
一、特殊类设计
只能在堆上创建对象
首先需要将其构造函数设为私有
其次就是借助静态成员函数来得到对象
同时,还需将拷贝构造删掉,否则也可以在栈上创建对象
只能在栈上创建对象
同上,一样需要将构造函数私有
然后借助静态成员函数来得到对象
如果new时初始化,即有拷贝构造,那一样可以在堆上创建对象,但这里不能将拷贝构造删掉,否则就无法得到对象,因为上图函数匿名对象时,也需要拷贝构造
所以这里需要将new屏蔽掉
不能被拷贝
C++98
单例模式
概念:一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全 局访问点,该实例被所有程序模块共享
下面的饿汉模式和懒汉模式都是以统计快速排序递归次数为例
饿汉模式
概念:提前准备好,随时可以吃,在main函数之前就创建好了单例对象,程序随时可以访问这个单例对象
成员变量有3个,一个是该类的静态成员对象,一个用来统计次数,另一个则用来保存每次快速排序分出的区间
首先需要将构造函数设为私有,以及将拷贝构造给删掉
同时还需定义该类的静态成员对象
用一个静态成员函数来得到该类的静态成员对象
下图第一个函数返回次数的值,第二个来对次数增加,第三个则是将区间保存至vector中
在快速排序中调用上述函数
测试用例
打印调用的次数,该快速排序进行了优化,区间很小时,借助了插入排序,所以次数偏少了一些
懒汉模式
概念:事先没有准备好,第一次访问时,才创建单例对象
和饿汉模式一样,也有3个成员变量,只不过该类对象改为了对象指针
定义该对象指针
获取对象
除了获取对象有区别外,其余成员函数与饿汉模式一致!
上述第一次获取对象时会存在线程安全问题,比如t1和t2线程同时进入if语句,t2线程先创建对象返回,然后t2将次数增加,而t1又创建对象,次数就会发生变化,所以会出现线程安全问题
解决方式还是加锁
声明一个锁的成员变量以及定义
下图这种情况是双检查加锁,外面套一层if语句是为了提高效率,比如t1已经创建好对象了,而t2再来时,就不会再加锁了
单例对象回收问题
一般懒汉的单例对象,不需要回收,因为进程正常结束,资源都会还给系统,这个对象只有一个系统自动回收也没什么问题,如果在单例对象释放析构时,有一些要完成的动作,比如要记录日志等等,那就可以定义一个回收类,直接定义在类内部即可,如下图
在该类中再加一个静态成员变量gc,以及类外定义gc
下图这种写法在C++11中也可以,比较简洁,因为C++11进行了优化,所以static sInst对象构造初始化是线程安全的,但在C++98中多线程调用时,static sInst对象构造初始化并不能保证下线程安全
对比饿汉模式和懒汉模式
饿汉模式
优点:简单
缺点:
无法控制创建单例对象初始化顺序,假如两个单例类A和B,要求A单例先创建,B单例后创建,B的创建依赖A;
如果单例对象初始化很费时间,会导致程序启动慢,就像卡死了一样
懒汉模式
优点:
对应饿汉模式的两个缺点
缺点
相对复杂一些,尤其还要控制线程安全的问题
二、类型转换
为什么C++会提出规范类型转换
因为C++兼容C,也就会保留C的隐士类型转换和强制类型转换,但这往往会导致在程序出现一些问题,如下图,end会提升成无符号整形,所以不可能会小于0,所以C++提出了四种类型转换
提示:隐士类型转换:相近类型--意义相似的类型
如下图,如果pa指向的父类对象,那么则转换不成功,返回nullptr,如果pa指向的子类对象,那么则转换成功,返回对象指针
注意: