4.6 函数私有化C语言的语句非常简单,关键词也少得可怜,关于变量和函数的修饰符也就只有区区几个,因此一个关键词有时候有着多重含义,这也就是为何C语言明明非常简单,但是用起来又非常复杂的原因之一。C语言关键词珍贵的这个特点,一般被称为C语言的缺陷。私有化这个概念,指的是,当我们创建好了一个功能模块代码之后,准备给别人调用,但是一般我们写C语言的时候,除了提供给别人调用的函数和变量之外,还有一些不希望给他们调用的函数或者变量。那这里可能有人会问了,不希望给他们调用那你还定义这些函数和变量干嘛?不给他们调用可以给你自己调用!举个例子来说,当我们在做一个GUI库(Graphic User Interface,图形用户界面)时,也就是类似于我们玩Windows时候展现的图形窗口库,希望这个GUI库可以被多种硬件平台移植使用。比如这个库即可以跑在51单片机上,又可以跑在STM32单片机上面。由于我们面对的每个硬件平台都是不通用的,随时会被移植掉的,因此具体这些硬件驱动如何去做,我们不关心,只是留出一些函数接口让用户自行根据移植手册去补充,这是第一点。第二点是,由于我们面对的用户是不同的,因此不同的用户可能会用这些图形库做不同的功能,比如Edward要在这块区域画个圆圈,Demon要在那个区域做个窗口,因此我这个GUI在设计时肯定要给不同的用户留出调用的接口。对于这些接口来说,我们只希望用户可以使用我整个代码里面指定给他调用的函数,有很多函数我不希望他去调用或修改,比如如何画一个圆,如何画一个三角形,具体如何去绘制这些图形细节的函数,比如如何去对一条直线插值,这些函数统统不需要用户知道,更不需要它调用。他所需要调用函数接口仅仅是,输入一个圆心坐标,输入一个半径,接着画圆的细节就交给我们的GUI即可。而这里的如何画圆函数即是我们这里所要讲的函数私有化问题。由于私有化是C++代表的“面向对象”编程思想兴起之后才出现的概念,因此很多书上都说C语言是一种面向过程的语言,C++即是面向过程又是面向对象的语言,C#是面向对象的编程语言云云,其实这个是不对的,面向对象程序设计,仅仅是一种编程思想。本书不展开面向对象和面向过程的区别,因为这个不好解释,只有等哪天你自己领悟了就明白了。我们前面讲了但凡是static修饰的变量,都不能被声明。这条规则对于函数也一样适用,因此我们才可以实现使用static关键词对函数进行私有化。接下来,我们用一个编程实例来说明函数的私有化问题。我们知道做包子的时候是需要经过和面,醒面,包包子,醒面,蒸包子这六个过程的,假设我们现在要做一个餐饮流水线的包子环节设备控制器,并且提供API给主函数使用,因为只有主函数才知道什么时候要包包子,什么时候要做饭。而主函数是不关心我们包子具体包的步骤的,这个包包子的步骤就相当于我们之前说的“面向过程”的语句。现在由于没有相应的执行机构,我们暂定用printf函数打印到屏幕上去。另外,我们再做一个定时器模块模拟给每一个步骤提供时间基准,定时器很简单,就是一个64位的变量,一直做自加。在这个例子中,具体和面函数,醒面函数等这些具体包包子的函数都是不希望被主函数调用的,万一被主函数调用了,那么这个蒸包子的过程可能就会出现异常,可能包子都做不好,因此一定要讲这些函数私有化。而整个包包子的功能模块,应该提供一个接口函数给主函数,并且允许主函数指定包多少笼包子。包包子的代码如图4-6-1所示。图4-6-1 Make buns源程序其中,这些蒸包子,和面,醒面等函数都是属于私有化函数,因此main函数里面是不可见的,main函数唯一可见的就是“Makebuns.h“文件里面声明的“MakeBunsProcess”函数。图4-6-2里面是剩余的源代码。图4-6-2“包包子”程序剩余代码而最终的运行结果如图4-6-3所示。图4-6-3 程序运行结果