苟哥的笔记本
首页
文章归档
关于
文章归档
关于
首页
编程
正文
C++单例模式为啥是这样的?
苟哥
2021-10-29 PM
940℃
0条
单例类也是一个类,只不过它有些特殊,单例模式有以下3个特征(原则): 1、单例类只能有一个实例对象; 2、单例类的对象必须由单例类自行创建; 3、单例类对外提供一个接口访问该单例的实例。 那么我们来看看单例类是如何由普通类“演变”而来的吧! ------------ 我们先定义一个普通类Beijing: ```cpp class Beijing { public: string title; void show() { cout << "Welcome to " << title << endl; } }; ``` 如果我们什么都不做,那么Beijing默认带有无参构造和拷贝构造,这样就违背了原则1:**单例类只能有一个实例对象**,如下test()执行是没问题的(省略头文件): ```cpp class Beijing { public: string title; void show() { cout << "Welcome to " << title << endl; } }; void test() { Beijing bj; Beijing fj; bj.title = "北京"; fj.title = "福建"; bj.show(); fj.show(); } int main() { test(); return 0; } ``` 为了满足原则1,我们就要想办法不让Beijing被轻易实例化,因此我们可以显示定义无参构造和拷贝构造,并将它们设为私有方法,Beijing代码修改如下: ```cpp class Beijing { public: string title; void show() { cout << "Welcome to " << title << endl; } private: Beijing(){} Beijing(Beijing &b) {} }; ``` 此时,test()无法编译通过了,说明原则1得以满足。 当你正洋洋得意之时,突然想到苦笑不得的问题“不能被实例化,那这个类不是废了吗?压根不能被使用”,原则1说的是只能有一个实例对象,而不是不能被实例化,因此我们必须想到个方法可以实例化单例类本身,也就是原则2。 我们可以借助静态成员变量来实现,定义一个指向当前类实例的指针,Beijing类修改如下: ```cpp class Beijing { public: string title; static Beijing* p; //指向类本身 void show() { cout << "Welcome to " << title << endl; } private: Beijing(){} Beijing(Beijing &b) {} }; Beijing* Beijing::p = new Beijing; ``` 写个test2()方法测试,代码如下: ```cpp class Beijing { public: string title; static Beijing* p; void show() { cout << "Welcome to " << title << endl; } private: Beijing(){} Beijing(Beijing &b) {} }; Beijing* Beijing::p = new Beijing; void test1() { Beijing* p_bj = Beijing::p; p_bj->title = "北京"; Beijing* p_fj = Beijing::p; p_fj->title = "福建"; p_bj->show(); p_fj->show(); } int main() { test1(); return 0; } ``` 运行结果如下:  运行结果正常。 等等,假设某个开发小伙伴使坏,敲了几行代码: ```cpp Beijing* p_jx = Beijing::p; p_jx->p = NULL; //因为p变量是public属性,因此可被修改 ``` 那么后面代码要想使用Beijing都不可能了,因为Beijing::p已指向NULL。因此,我们还需对p变量进行安全保护起来——将其设为private变量吧,Beijing修改如下: ```cpp class Beijing { public: string title; void show() { cout << "Welcome to " << title << endl; } private: static Beijing* p; Beijing(){} Beijing(Beijing &b) {} }; ``` 这样,再也不怕小明同学搞破坏了。。。 当你忍不住再执行test1()方法准备迎接胜利时刻之时,“咚”,编译报错:joy:。提示Beijing::p无法被调用,对哦,p已经被设置为private属性了,怎么还能再被外部调用呢。不过这个比较好解决,既然外人用不了,那我让你的家人给我总行了吧:grin:,这就是原则3的要求了。定义一个外部可访问的成员方法,返回成员变量p,Beijing修改如下: ```cpp class Beijing { public: string title; void show() { cout << "Welcome to " << title << endl; } static Beijing* getInstance() { return p; } private: static Beijing* p; Beijing(){} Beijing(Beijing &b) {} }; ``` 此时,我们test1()应该修改如下: ```cpp void test1() { Beijing* p_bj = Beijing::getInstance(); p_bj->title = "北京"; Beijing* p_fj = Beijing::getInstance(); p_fj->title = "福建"; p_bj->show(); p_fj->show(); } ``` 至此,我们已经看到了普通类一步步演变为单例类的过程,你可以对单例类说“我是看着你长大的”:v:。
标签:
C++
,
单例类
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
http://www.i366211.com/archives/180/
上一篇
编译安装Mysql5.7
下一篇
变量
取消回复
评论啦~
提交评论
栏目分类
软件安装
10
开发工具
8
算法
2
测试
1
架构
3
填坑记
2
开源
6
科普
6
私域
2
读书笔记
4
编程
48
运营
3
管理
1
标签云
算法
C程序设计语言
C语言
Java
mysql
PHP
ffmpeg
golang
VueJs
脚手架
VueJs实战项目
Intellij IDEA
Centos7
Hyperf
抖音运营
杰克韦尔奇
跌荡一百年
生成海量测试数据
企业管理
习题2-3
习题2-4
习题2-6
异常分类
File
习题2-7
习题2-8
习题2-9
习题3-3
习题3-4
习题3-5
友情链接
申请
SaaS引擎
机器人框架
京东捡漏