要搞清楚这个问题,你必须搞清楚以下4点:
1、什么是面向过程的程序设计思想?
2、用面向过程的程序设计思想编写程序时有什么问题?
3、为解决面向过程思想中的致命缺陷,于是C语言引入了封装类,进入了面向对象的C++时代.
4、为什么要叫面向对象?
1、什么是面向过程的程序设计思想?
你见过下面这个程序吗?
#include<stdio.h>
int main(void)
{
intmax(intx,inty);
inta,b,c;
scanf("%d,%d",&a,&b);
c=max(a,b);
printf("max=%d\n",c);
return 0;
}
intmax(intx,inty)
{
intz;
if(x>y)z=x;
elsez=y;
returnz;
}
这是谭浩强《c语言程序设计》中例1.3的程序。用这个例子我先给你说明什么是面向过程?
这样,就先解决了,什么是面向过程的程序设计思想的问题。
2、面向过程的程序设计思想,在编写程序时有什么问题呢?
好,我在举一个熟悉的简单的例子:求解2个数a,b的最大值max,最小值min和平均值average,有两种实现方法:
方法1、使用全局变量实现.
#include〈stdio.h〉
floata,b;/*-----------2个全局变量--------*/
voidmax(void)/*求任意2个数字的最大值。*/{
floatm;
m=a>b?a:b;
printf("%f\n",m);
}
void min(void)/*求任意2个数字的最小值。*/{
floatm;
m=a<b?a:b;
printf("%f\n",m);
}
voidaverage(void)/*求任意2个数字的平均值。*/{
floatm;
m=(a+b)/2;
printf("%f\n",m);}
intmain(void)
{
scanf("%f%f",&a,&b);
max();
min();
average();return 0;
}
方法2、用局部变量求解,相对上面的程序作了一些简化,学完C的看这应该没有问题.
/********************************************************/
#include〈stdio.h〉
voidmax(floata,floatb){printf("%f\n",a>b?a:b);}/*省略m,直接输出最大值*/
voidmin(floata,floatb){printf("%f\n",a<b?a:b);}/*省略m,直接输出最小值*/
voidaverage(floata,floatb){printf("%f\n",(a+b)/2);}/*省略m,直接输出平均值*/
int main(void)
{
floata,b;
scanf("%f%f",&a,&b);
max(a,b);
min(a,b);
average(a,b);return 0;
}
上面2个程序的区别关键就在于:变量a,b!在方法1中,a,b定义成了全局变量;而在方法2中,a,b定义成了局部变量。这里有一个前题假设:读者都知道什么是全局变量,什么是局部变量,
现在,你说说上面的2种方法,哪个更好?是把a,b定义成全局变量的好,还是定义成局部变量的好?其实都好,也都不好。为什么呢?我想起《潜伏》中的一段话:这里有2根黄金,你说哪根是高尚的,哪根是低俗的呢?
上面的两个程序中,无论哪一个,都有4个函数。方法1中,a,b是定义成全局变量,那么此时,程序中的4个函数都可以使用或更改a和b;全局变量a,b真的是好方便哦,它在4个函数中都能读写;专业些说,就是实现了4个函数的数据共享,从而弥补了局部变量只能在一个函数中被使用的不足。
这里所说的数据共享有2个含义:
a、全局变量可以被4个函数读(读的意思就是在全局变量被使用后,它的值不变;)
b、全局变量可以被4个函数改;(改的意思就是在全局变量被使用后,它的值变了;)
也就是说:全局变量的值既可被4个函数读取,也可以被4个函数改变; 问题又来了,什么问题呢?
问题就在于:全局变量a和b的值太容易被改变了!!!!!在a和b定义语句后面的所有函数,谁都能改变a,b的值;
假设我的程序功能在不断的增强,改进,那么程序中的函数的数量必然在不断的增多,在某个时刻,我的这个程序中有了1000个函数!
MYGOD!,如果这时,我对a或b的赋值发生一点点的错误,我只有把1000个函数从头开始,仔细的进行检查,检查所有和a或b有关的语句!!!
最不幸运的情况是,我可能会查遍所有的1000个函数,才可能找到问题所在;或许啊,还不是检查1遍、2遍,也许是10遍20遍,那时,我将欲哭无泪..........
全局变量的这个问题,简直太恐怖了,咋办??????????????????????????????????
那么,让我们回头看看方法2使用局部变量定义a,b的那个例子。审视了这个程序后,我们发现,使用局部变量定义a和b,可以避免a、b被其他函数随意修改,但同时其他函数也不能随意读取这两个变量的值。即,在max(),min(),average中,使用了main()里定义的a,b,但是,需要通过参数传递的办法,从主调函数main()传递到其他3个函数中;同时我们也发现,在max(),min(),average中,我们无法改变main()中a,b的值,原因就是C语言中,从主调函数可以将数据传入被调函数,反之不可!!!即著名的参数单向值传递原理!
我们看到:局部变量优点在于被封装,缺点在于封装的太死,使用起来不太方便;全局变量优点在于被共享,缺点在于不能得到某个函数的封装保护,太容易被误改。那么,到底a,b是定义为全局变量好,还是定义为局部变量好呢?我们陷入了两难的境地........................
注意,这里使用了一个词:封装。有什么办法可以,即让我们享受到,类似函数对其局部变量的封装保护,又能象全局变量一样,方便的读取写入,唯一的办法就是:限制全局变量的使用范围!!!在我们的C语言中,就对这种限制的思想,进行了成功尝试,这种尝试,就是把全局变量定义成静态全局变量!同时,在C语言中对于函数也进行了类似的封装保护的尝试,于是就有了内部函数和外部函数的区别,这些都是封装的可贵探索。一切的一切都是为了使全局变量,出错的范围尽可能的缩小!注意,到此处,我们解决了一个重要的问题是:“有什么办法可以让我们的变量即有局部变量的封装优点,而使用又能象全局变量一样方便?” 唯一的办法: “对全局变量的使用范围做出合理的限制!”这个方法在c++被发挥到了极致,具体的,就是体现在类中!
为解决面向过程思想中的致命缺陷,于是C语言引入了封装类,进入了面向对象的C++时代.
3、为解决面向过程思想中的致命缺陷,于是C语言引入了封装类,进入了面向对象的C++时代.
好,我现在把上面方法2的程序改写为C++的程序,不要怕看不懂,你不会看不懂的,加油看,程序如下:
#include<stdio.h>
classtwonum{
public:
twonum(constfloat,constfloat);
voidmin();/*求任意2个数字的最小值。*/
voidmax();/*求任意2个数字的最大值。*/
voidaverage();/*求任意2个数字的平均值。*/
private:
floata,b;/*-----------2个全局变量--------*/
};
twonum::twonum(constfloatx=0,constfloaty=0)
{a=x;b=y;}
voidtwonum::max()/*求任意2个数字的最大值。*/
{floatm;
m=a>b?a:b;
printf("%f\n",m);
}
voidtwonum::min()/*求任意2个数字的最小值。*/{floatm;
m=a<b?a:b;
printf("%f\n",m);
}
voidtwonum::average()/*求任意2个数字的平均值。*/
{floatm;
m=(a+b)/2.0;
printf("%f\n",m);
}
voidmain()
{floata,b;
scanf("%f%f",&a,&b);
twonumm(a,b);
m.max();
m.min();
m.average();
}
在上面纷繁复杂的程序中,我们仍然能依稀看到方法2程序的模样,我们看看是如何改写的:
1),变量a和b的声明,以及除main外的其他3个函数的声明被放入一个带有class的大括号中,如下:
classtwonum
{
public:
twonum(constfloat,constfloat);
================================================
voidmin();/*求任意2个数字的最小值。*/
voidmax();/*求任意2个数字的最大值。*/
voidaverage();/*求任意2个数字的平均值。*/
================================================
private:
floata,b;/*-----------2个全局变量--------*/
}
上面的这个带有名字的大括号,就是关键的关键所在!!!!!!!!!!!!!!!!!!!!!!!!我们都知道,大括号表示一个范围,那么这个范围表示什么含义呢? !!!!!!!!!!!!!!
我们的思想是:用private:floata,b;声明的a,b变量,~~~~能且只能~~~~~被这个大括号中的声明的函数读写.此时的a,b不是被限制在某个函数中,做局部变量,也不是对全部函数开放,做全局变量,而是限制在这对class大扩号间,即这个大括号中声明的函数,可以对他进行读写,这个大括号中有哪些函数呢?max(),min(),average(),当然多了一个twonum()函数,和我们这里的讨论关系不大,我不说它.
在main()中,用twonumm(a,b);声明了变量m后,m中就有了a,b,也有了max(),min(),average()。m的max(),min(),average()共享使用a,b数据,不需要传递参数了.不是吗?不信你看: