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的东西,其实不是计算 机不能让你公开,而是你程序员自己要“声明”,这东西我只自己用,你们别来动我的。
而类的成员函数也是这么个道理。你说我们在类外面写一个函数处理这个类行不行?那肯 定是行的,为什么要定义类的专有函数呢?其实就是为了说明:“我自己的数据只有我自己 的函数用,其他人你们别来动我的。”
对初学者来说,不容易理解这一点的,因为你们写的程序太小了,没有感受到有几百几千 个变量的那种痛苦。但点出这一点,有利于我们理解这些知识到底用来解决什么问题的。