教C语言高手学C++(02)
类就是封装
大师:用集成电路搞设计,你比较熟悉吧?
小蔡:那当然了。我们接触硬件还是比较多的。一块集成电路,就是一个功能模块,我们根据需要选择各个模块,通过连线把它们连接起来,就够构成了整个系统。
大师:其实软件设计,何尝也不是集成电路的设计思想呢。
我们设计整个系统的时候,也是分解策略,把整个系统,分解成若干的功能模块,然后分别实现,最后联合起来调试。
小蔡:还真是这个道理。
大师:那你说,那个语法特点,最像集成电路呢?
小蔡开始谨慎起来:
“对C语言来说,当然是函数这种语法了。一个函数,就是一个功能模块,就像集成电路一样,可以被重复调用,就像系统中使用相同的集成电路一样。”
“聪明!”大师微笑,
“看来你的C语言基础确实不错。
的确是这样的,函数算一个功能模块的集合。并不是每个函数,都那么的内聚,大多数函数,在操作的时候,常常要依赖系统中其他变量的结果,或者说,要改变系统中某个变量的值。
”
小蔡有些疑惑:你举一个案例。
大师说:你看前面的案例:
“ int deprint(char *s){ if(noisy) printf(……); }。这段代码,就根据noisy这个变量的值来决定运行状态。”
小蔡突然有些明白了:对,你看,on()和off()两个函数的执行,还改变了noisy的值。
大师接口到:对阿,实际上,deprint(),on()和off() 这样的函数,关系非常紧密,都和noisy这个变量息息相关。他们的耦合相关性如此之强,但是C语言,居然没有提供一种机制,把他们聚合在一起,成为一个模块。
小蔡有些感慨:对啊,我们在编写有些模块的时候,常常把一些全局变量和函数放在同一个文件中,以形成单独模块。而实际上,C++提供的classs这种封装方式,把相关的函数和变量,聚合在一起,成为一个独立的模块。更加方便了。
“哈哈,孺子可教。你现在明白class的第一个特性,封装的意义了吧?”大师笑道。
“嗯,基本明白了,我以后,在程序中,就会用到这种特性,把相关的函数和变量,封装在同一个类中。这样还不容易出错。”小蔡感叹道。
“对,所以,封装是面向对象的第一个重要特点。”大师总结道,
“这使得我们使用别人的功能模块的时候,也要简单很多,告诉我们有哪些类,每个类实现了那些功能即可。”
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
另外一个视角看类
“你的理解能力很强。实际上,我们使用class这种机制,还有另外一层意思。更加接近描述真实的物理世界。”
大师徐徐到:“在C中,我们如何描述客观世界呢?比如,一辆汽车。”
小蔡:当然是用struct,我们分别记录汽车的长,高,宽等特性,有几个轮子,发动机型号……等等。
大师点头:“对,其实客观事物,总有这样那样的属性,我们可以抽象成int,float,char等类型来描述,然后集合起来,成为一种新的类型即可。”
“但是,这只是一种数据的描述,万事万物皆对象,对象除了这些数据属性之外,还有很多行为,这些行为,我们把他们抽象成各种函数,在C++中,我们叫他们方法。”
“任何对象,都是由属性和方法构成,但是,C语言基本上把他们隔离开了,C++只不过把它们自然的聚合在一起。”
“class,就是一种更接近客观事物的抽象,你说是不是?”
小蔡点头:对,其实,这是和前面的观点相一致的。比如我们编写的链表程序,头、尾,是他们的属性,查找,插入……等是他们的方法。我们把它们封装在一起,更接近我们大脑中链表的抽象情况。
“呵呵,你学得很快。”大师比较高兴,“我们来看看具体的语法吧。
类类型用关键字class定义。简单地说,用这个关键字定义的类型都称作类。比如,我们要描述计算机屏幕上的一个点,具体的语法形式如下,大师在纸上写了一个类:
class Point
{
private:
int Px, Py;
public:
Point() {Px = Py = 0; }
Point(int x, int y) {Px = x, Py = y; }
int &x(int );
int &y(int );
int drawMe ( );
int clearMe( );
};
你看,class关键字,后面加入类型名,然后用{ };把它们封装起来的这些内容,都是class的属性或者方法。
你第一次学习C++,最重要就是要明白这点。
其次,public:范围所定义的这些成员,不管属性还是方法,当然,一般是方法,是可以访问的,private:范围内定义的,是内部使用,不可访问。也就是说,
Point apoint;
apoint.Px=10;
后面这句,是不容许的。public和private的区别,是你要记住的第二点。
“嗯,其实我看过一点C++语法图书,private相当于模块内的局部变量,只有class内可以使用,外面是不可见的。”小蔡说道。
“对,从封装的角度,也是可以这么理解的。”
大师转向计算机,
“好了,具体类如何使用,我们到计算机上,给你一个完整的案例吧。”
说完,大师在屏幕上写了如下的代码:
#include <iostream.h>
class Point
{
public:
Point( ) { _x=0; _y=0; }
Point( int x, int y);
private:
int _x,_y;
public:
int x() { return _x; }
int y() { return _y; }
void Show() ;
};
Point::Point(int x,int y)
{
_x=x;
_y=y;
}
void Point::Show() //在类的外部实现类中定义的成员函数
{
cout << x() << "," << y() << "\n";
}
int main()
{
Point pt1, pt2(25,64);
pt1.Show();
pt2.Show();
cout<<"\n";
Point *ptrPoint=new Point;
ptrPoint->Show();
return 0;
}
然后执行的结果出来:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" />
“小蔡,上面的代码中,在成员函数Show()调用了其它成员函数x()和y(),并不需要使用成员选择符,从某种程度上说,也是因为他们在同一个模块内,使用了this指针。这些调用的隐含意义是this->x()和this->y()。”
“然而在主函数main()中调用成员函数Show()必须使用对象名pt1、pt2和成员选择符(.);另外,ptrPoint指向的对象的成员函数的调用使用的是成员选择符(->)。”
“这是我今天希望你记住的第三点。”
“好的,”小蔡点头在纸上记录。
“好了”,大师开始结束今天的讲课,“this指针的详细用法,你先回去看看书;另外,为啥运行结果图中:为什么pt1.Show()和ptrPoint->Show()运行结果一样?还有,为什么有的成员函数的定义和实现在一起?这三个内容,我下次讲课之前,先要考你哦,你回去准备一下吧。”
转载于:https://blog.51cto.com/jtclass/88429