写这篇文章的动机来源于网友purewinter在我的那篇《重读《设计模式》之学习笔记(三)--SINGLETON模式的疑惑》中的评论。
    在那篇文章中,我提供了如下一个用C++实现的Singletion模式的小例子:

class  ClxSingletonMEC
{
public :
    friend ClxSingletonMEC &  InstanceMEC();

private :
    ClxSingletonMEC() {};
    ClxSingletonMEC( const  ClxSingletonMEC  & lxSington) {};
};

ClxSingletonMEC &  InstanceMEC()
{
     static  ClxSingletonMEC Instance;
     return  Instance;
}

并指出,为了防止这个类的用户写出下面的代码:

ClxSingletonMEC lxMEC  =  InstanceMEC();  //  或者ClxSingletonMEC lxMEC(InstanceMEC());

类ClxSingletonMEC的拷贝构造函数必须是private的。
    而purewinter在评论中说道:“还需要把析构函数设为private,否则用户可以错误的delete掉它。”我本来想回复他说,如果析构函数也为private的,那么在程序退出时候调用类的析构函数时就会出现私有成员函数不能访问的错误。
    不过我在回复之前做了个试验。没想到的是,把类ClxSingletonMEC的析构函数设置为private后,程序能编译通过,并且能正常运行!通过在这个private的析构函数中设置断点我发现,这个private的析构函数确实被正常的调用了。
    上面的结果令我非常吃惊!同时也非常迷惑!为什么一个private的析构函数能被正常的调用呢?!这完全推翻了我以前对C++中访问权限(pbulic,protected,private)的理解。
    如果说对象Instance不是静态的,比如函数InstanceMEC()是这样的:

void  InstanceMEC()
{
    ClxSingletonMEC Instance;

//  下面省略……
}

那么,对象Instance在函数InstanceMEC()作用域结束的时候会被析构。这个时候,系统调用对象Instance的析构函数,因为函数InstanceMEC()是类ClxSingletonMEC的友元函数,所以可以访问类所有的成员函数,因此可以调用私有的析构函数将对象Instance析构。这个非常好理解。
    可是,在Singletion模式的例子代码中,类ClxSingletonMEC的友元函数InstanceMEC()中的对象Instance是一个静态对象。而静态对象(不管是全局的还是局部的)是一经构造,就存放在进程中的一个固定内存中,直到进程结束的时候才会由系统调用对象的析构函数而被析构掉。这也是上面的例子代码能保证Instance在进程中唯一的原因(不管用户调用多少次函数InstanceMEC(),只有第一次调用是真正的构造对象Instance,其他的是直接返回对象Instance,这也是static的特性)。也就是说,对象Instance被不是在函数InstanceMEC()中被析构的。那为什么对象Instance的私有析构函数还能被调用呢?
    经过一段时间的思索和代码测试,我发现了“罪魁祸首”--friend。在C++中,friend是破坏封装性的,友元函数可以不受访问权限的限制而访问类的任何成员。在Singletion模式的例子代码中,这正是利用了友元函数的这个特性来访问类的私有构造函数来创建类在进程中的唯一对象的。而C++的访问权限仅仅在源文件中有效,编译时C++编译器确保访问规则,但编译后的目标文件和库文件里是没有任何访问权限信息的。也就是说,由于对象Instance声明在类ClxSingletonMEC的友元函数InstanceMEC()内,在编译阶段编译器就生成了系统可以访问对象Instance的私有构造函数和私有析构函数的目标文件(至于是什么时候调用则是运行期确定的)。而对象Instance是静态的,会存放在进程中的一个固定内存中,是运行时期来决定的。在进程结束时,系统要清空进程堆空间,在调用对象Instance的析构函数时是不会判断该析构函数是否为私有(文件中根本没有任何访问权限信息),因为在编译时期就已经设定对象Instance的私有析构函数是可以被调用的。
    由此可见,C++中friend对封装性的破坏几乎是毁灭性的。

C++中friend对类封装性的强大破坏性相关推荐

  1. 简易售货机JAVA sql_求一个简易自动售货机的代码(java)要用创建类封装性,输出的时候要有提示语句,代码类似以下图片...

    展开全部 //Example类文件Example.java package cn.zhouhan; import java.util.Scanner; public class Example { s ...

  2. Java基础-学习笔记(六)——类的封装性

    1.类是模板,对象是具体的实例 2.如果成员函数中的局部变量与成员变量名一致,则该方法对这个变量名的访问是局部变量 class lesson1 {int age=9;void talk(){int a ...

  3. Python基础学习——面向对象编程(第一讲:面向对象概述、面向对象三个基本特征(封装性、继承性、多态性)、类和对象(定义类、创建和使用对象、实例变量、类变量、构造方法、实例方法、类方法、静态方法))

    面向对象是Python最重要的特性,在Python中一切数据类型都是面向对象的. 1.面向对象概述 面向对象的编程思想是,按照真实世界客观事物的自然规律进行分析,客观世界中存在什么样的实体,构建软件系 ...

  4. Java学习-类的隐藏机制(封装性)

    Java学习-类的隐藏机制(封装性) 1.封装的含义 2.类的setXXX 和 getXXX 3.this关键字 4.总结 1.封装的含义 封装(encapsulation)是面向对象的三要素之一(其 ...

  5. java子类创建过程_JAVA入门小小白学习中ing(匿名对象、封装性、继承性、子类对象的创建过程、spuer关键字(用法一))...

    小小白慢慢学习中ing 第十二天 努力努力 本日内容(匿名对象.封装性.继承性.子类对象的创建过程.spuer关键字) 1.匿名对象 创建对象的语法:Person p1 = new Person(); ...

  6. 类的封装性和信息隐蔽【C++】

    类的封装性和信息隐蔽[C++] 一.公用接口和私有实现的分离 C++通过类来实现封装性,把数据和与这些数据有关的操作封装在一个类中,或者说,类的作用是把数据和算法封装在用户声明的抽象数据类型中. 在类 ...

  7. 【JavaSE】类与对象--封装性

    文章目录 一.面向对象的三大特性 二.封装性 1.什么是封装性? 2.为什么要有封装性? 3.封装性的作用 4.封装性的实现步骤 5.访问限定修饰符 一.面向对象的三大特性 面向对象的三个基本特征是: ...

  8. python语言学习:python语言学习中的定义类、定义函数、封装api等详细攻略

    python语言学习:python语言学习中的定义类.定义函数.封装api等详细攻略 目录 python语言学习中的定义类 python语言学习中的定义函数 python语言学习中封装api pyth ...

  9. java中如何把时间封装成类,java-如何在不使用任何不推荐使用的类的情况下将日期从一种格式转换为另一种格式的日期对象?...

    java-如何在不使用任何不推荐使用的类的情况下将日期从一种格式转换为另一种格式的日期对象? 我想将date1格式的日期转换为date2格式的日期对象. SimpleDateFormat simple ...

最新文章

  1. qt windows 静态编译_VS+QT工程配置问题
  2. Java多态-如何理解父类引用指向子类对象
  3. C#数据库操作一点相关点。。。
  4. Ubuntu软件包deb的安装.
  5. 解决vue里iscroll(better-scroll)点击触发两次和初始化无法滚动问题!
  6. Win10系列:VC++ 定时器
  7. Javascript——DOM编程
  8. 倒角距离(Chamfer distance)和earth mover‘s diatance
  9. Zabbix监控Redis状态(内含Zabbix、Redis福利资料)
  10. 循环取矩阵的某行_一文搞懂RNN(循环神经网络)基础篇
  11. 无根树的同构:Hash最小表示法(bzoj 4337: BJOI2015 树的同构)
  12. MCU——矩阵键盘扫描问题记录
  13. 【题解】守望者的逃离
  14. 阴阳师ios和android,《阴阳师》App Store表现优异,安卓苹果惊喜同服
  15. vtk读取CT序列mip投影
  16. 标准符号代表的意思汇总
  17. 任正非的忠告:不赚钱的产品就关闭压缩
  18. 常用计算机控制芯片有哪些,电脑基本芯片的认识的常用知识介绍
  19. python 文件 .py .pyc .pyw .pyo .pyd
  20. 关于MATLAB中clear的用法

热门文章

  1. 安全分析能力的核心能力
  2. Linux 修复openssl漏洞
  3. Hive的HQL语句及数据倾斜解决方案
  4. python变量的存储机制,关于python:python的变量缓存机制
  5. 最简单的几个界面设计原则
  6. PB powerbuilder timing类
  7. 微信支撑10亿用户背后核心技术,竟然是它...
  8. 华为云桌面windows版客户端_华为云——云桌面,开启企业云办公时代
  9. 2016年全国管理类硕士研究生考试——综合能力复习心得
  10. WM8960音频播放