Skip to content

Latest commit

 

History

History
75 lines (53 loc) · 3.7 KB

12.rst

File metadata and controls

75 lines (53 loc) · 3.7 KB
Authors: Kenneth Lee
Version: 0.1
Date: 2022-11-03
Status: Draft

什么叫封装

这一章的内容适合在学习类以后看。

一直说类是为了增强“封装”性,但对于初学者来说,为什么要封装,这是一件比较奇怪的 事情。

有一种说法,说飞机的控制软件,大部分变量都是全局变量,你要访问到谁,就用那个名 字的变量。所以这种软件很少人敢修改,因为它有几万个全局变量,而这些变量可以有几 百个函数都用到了。这种所有的变量谁能看见的,就叫“没有封装”,它很方便,很自由, 想用谁就用谁。但它的缺点也是很明显的,你不知道哪个函数用到它。就算你知道,你也 不知道它怎么用它的,你不敢肯定你修改一下会不会导致那个函数就错了。

比如你用一个变量表示输入参数的格式,你定义一个全局变量int input_format。这个变 量用1表示二进制,2表示8进制,3表示16进制,其他值无效。你是这个意思了,另一个函 数也想这么干,所以它看见你的名字了,他也用这个,但他用2表示而进制,20表示16进制, 其他值无效。你们互相之间的代码就打架了,这个程序就会出错。

最简单的解决方案,你的全局变量放在你的文件里面,我们放在我的文件里面。C/C++的关 键字static就起这个作用,如果你不加static,它就是所有文件都可以访问的,如果加上了, 它就是本文件才能访问的。两个文件用同一个名字,互相不影响。

更极端的,你可以放在函数里面,只有这个函数能访问。static的函数变量本质上也是全 局变量,只是其他函数不能访问而已。

但这不够好,如果你的input_format和我的input_format都在几个文件中要共享怎么办呢? 所以最好不要叫一样的名字,最好你的叫your_input_format,我的叫my_input_format。 这个your和my的前缀,就是用来区分的不同名字的,我们把它称为“名称空间”(namespace)。

但这个东西写起来太长了,C++干脆给这个提供了语法支持。这就是你每次写例子的时候那 个using namespace std的功能。你可以把你的东西一概定义在一个名称空间里面:

namespace my {
  int input_format;
}
namespace your {
  int input_format;
}

using namespace my;
using namespace std;

cout << input_format << endl;

这样你就不用写那么多my_xxx,你哪里要用哪个名称空间,直接用那个名称空间就可以了。 如果你不using那个namespace,你就要这样写:

std::cout << my::input_format << std::endl;

这就叫封装,我自己写的函数逻辑,我只保证这个变量我自己用额时候是对的,其他人你 别用我的,你要用,你自己定义一个去。

不但变量是这样,所有名字都是这样。

所以,你看类的概念搞了那么多什么private,protected,public的东西,其实不是计算 机不能让你公开,而是你程序员自己要“声明”,这东西我只自己用,你们别来动我的。

而类的成员函数也是这么个道理。你说我们在类外面写一个函数处理这个类行不行?那肯 定是行的,为什么要定义类的专有函数呢?其实就是为了说明:“我自己的数据只有我自己 的函数用,其他人你们别来动我的。”

对初学者来说,不容易理解这一点的,因为你们写的程序太小了,没有感受到有几百几千 个变量的那种痛苦。但点出这一点,有利于我们理解这些知识到底用来解决什么问题的。