第2章类和对象•2.1面向对象程序设计方法概述•2.2类的声明和对象的定义•2.3类的成员函数•2.4对象成员的引用•2.5类和对象的简单应用•2.6类的封闭性和信息隐蔽2.1面向对象程序设计方法概述•2.1.1面向过程的程序设计的特点•2.1.2从面向过程向面向对象的思维转变•2.1.3面向对象程序设计的特点2.1.1面向过程的程序设计的特点图2.1面向过程的程序设计的特点传统的面向过程程序设计是围绕功能进行的,用一个函数实现一个功能,一个函数可以使用任何一组数据,一组数据可以被多个函数使用。当程序规模越来越大,数据越来越多,操作越来越复杂,这种方法容易出现错误,程序员往往感到难以应付。2.1.2PO向OO的思维转变•从面向过程向面向对象的思维转变–面向过程:ProcessOriented(PO)–面向对象:ObjectOriented(OO)–例子:“兔子走路”和“人走路”•面向过程的处理方式首先,写一个“兔子”结构体。structrabbit{}r;然后是一个“兔子走路”的算法。voidrabbitWalk(rabbitr);最后对“兔子”使用“兔子走路”算法。rabbitWalk(r);“人走路”与“兔子走路”类似:structhuman{}h;voidhumanWalk(humanh);humanWalk(h);数据结构算法程序++=调用算法•程序“兔子走路”=数据结构“兔子”+算法“兔子走路”。•程序“人走路”=数据结构“人”+算法“人走路”。•如果数据结构“人”+算法“兔子走路”会怎样呢?–这显然是不允许的,可是将算法和数据结构分开定义,很可能导致这样奇怪的组合。•面向对象的处理方式首先,首先创建一个“兔子”对象classrabbit{};rabbitr;然后由于兔子需要“走路”这一行为,因此向类中添加这一行为classrabbit{voidwalk(){}};最后让“兔子”对象执行它的行为r.walk();同样地,“人走路”的程序可以这样实现:classhuman:publicanimal{voidwalk(){}};humanh;h.walk();数据结构算法兔子对象+=classrabbit{voidwalk(){}}数据结构算法人对象+=调用对象的行为++程序=•在这里,是对象调用它自己的行为。两个“走路”行为虽然同名,但是它们是不相关的。由对象自己决定它们调用哪个“走路”行为,而程序员要做的,只是让对象执行它们的“走路”行为。对象“人”没有兔子的走路行为,所以让人用兔子走路的方法是不可能的。2.1.3面向对象程序设计的特点•对于规模比较小的程序,程序员可以直接编写出一个面向过程的程序,能详细地描述每一瞬间的数据结构和对其操作的过程。但是当程序规模越来越大,面向过程的程序语言就显得力不从心,面向对象程序设计语言就应运而生,C++就是其中的一个成员。1.对象•什么是对象?–对象是与现实世界相关的一个实例。比如一只“喜羊羊”是一个对象。•哪些东西可以是对象?–对象可以是自然物体,也可以是社会中的一种组织结构(班级、系、学校)、或者某个动作(喜洋洋“从学校走到村长的家”)。复杂的对象可以由简单的对象组成,例如火车站对象包含售票处、行李房、候车室和站台、信号灯、铁轨和通信设施等对象。•对象包含有哪些内容?–一个对象往往包含一组属性和一组行为。如电视机包括生产厂家、品牌、屏幕尺寸等是一组属性,开机、关机、选择频道、调节音量、调节彩色等是一组行为。•C++的对象包含什么?–在C++中,每个对象由数据和函数(操作代码)两部分组成。数据代表了属性,函数是对数据操作的代码,代表了行为。例如三条边长是三角形的属性,利用三条边长计算三角形面积、输出计算结果,实现这些操作的代码就是对象的行为,在程序设计中又称方法。2.类•类是对对象的抽象,用来表示同一类事物。它关注事物本质特征,对象是具体的。–例如一只“喜羊羊”是一个对象,抽象出来的“羊”是一个类。•对象是类的实例化–例如“羊”这个类包含了“羊的名字”这个属性,但是没有规定这个属性的具体值是什么。从类“羊”实例化出“喜洋洋”这个对象,该对象的名字属性的值是喜洋洋。–类是一个类型,对象是一个变量(联想一下结构体类型和结构体变量)3.封装与信息隐蔽对一个对象进行封装处理,把它的一部分属性和功能向外界屏蔽,从外面看不到这些属性和功能。例如录像机里有电路板和机械控制部件,由于有机壳的保护,在外面只看到一个黑箱子,在它的表面有若干个按键。人们只需知道这些按键的功能即可操作录像机。而不必知道录象机的工作原理和系统结构。•在设计一个对象时,要周密地考虑如何进行封装,把不必让外界知道的部分隐蔽起来。也就是说,把对象的内部实现和外部行为分隔开来。•封装性是面向对象程序设计的一个重要特点,封装在此有两个含义:•①把有关的数据和操作代码封装在一个对象中,形成程序中的一个基本单位,各个对象之间相互独立,互不干扰。②把对象中的某些部分对外隐蔽,只留下与外界联系的接口接收外界的消息,这种对外界隐蔽的做法称为信息屏蔽。封装把对象内部实现与外部分隔开,外界不了解对象内部的具体细节,其实外界也不需要了解。外界需要真正了解的是对象的对外接口。C++对象中的公有函数就是对象的对外接口。外界通过调用公有函数,访问对象中的数据成员,完成指定的操作。4继承与组合•如果已经建立名为A的类,现要建立一个名为B的类,而B类与A类的内容基本相同,只是在A类基础上增加了一些属性和行为,这样只需在A类的基础上添加新内容即可,这就是面向对象程序设计中的继承机制。(A和B是is-a(是)的关系)•可以在一个新类A的定义中使用另外一个对象b。这就是组合(composition)。(A和b是has-a(拥有)的关系)•继承和组合都是实现程序复用(reusibility)的基本手段。原本有一个类叫“羊”。但现在需要一个“会说话的羊”的对象,要怎么做呢?方案一:方案二:这是一个继承的例子,就好比这种羊进化出一个新的具有speak行为的品种。这是一种组合的例子,这种羊还是不会说话,但是它得到了一个发声器,利用这个发声器的speak行为替羊说话。5.多态性•多个相似而不完全相同的对象,收到外界给的同一个消息时,它们各自执行不同的操作,这种现象叫多态现象。•例如在windows中,用鼠标双击一个文件对象时,如果它是可执行文件则会执行文件中的程序,如果它是一个文本文件则会启动一个编辑器来打开这个文件,这就是面向对象程序设计中的多态性一个实际例子。•在C++中所谓多态性是指:由继承而产生的新类,它的对象对同一个消息会作出不同的响应。大森林里要举行跑步比赛,小动物们都来的报名。•PO(面向过程):–大象:我是大象,我来报名。–管理员:好的,请你用大象跑步的方式参加比赛。–犀牛:我是犀牛,我来报名。–管理员:犀牛?应该是一种牛吧?请你用牛跑步的方式参加比赛。–小黄牛:我是小黄,我来报名。–管理员:小黄是什么?–没有“小黄跑步”这种跑步方式,你不能参加跑步比赛。结局:大象完成了比赛。犀牛中途退赛了,因为牛的跑步方式不适合它。小黄牛没有参赛比赛。•OO(面向过程):–管理员:我不管你是什么动物,也不管你以什么方式跑步。只要你有跑步这种行为,你就可以参加比赛,并且以你自己的跑步方式跑步。结局:大家都参加了比赛,且以自己的方式完成了比赛。2.2类的声明和对象的定义在面向对象程序设计中,要使用大量的对象,要程序员对问题进行分析抽象出类的概念,在设计程序时首先要声明类类型,然后再定义类类型变量即对象。•2.2.1类和对象的关系•2.2.2声明类类型•2.2.3定义对象•2.2.4类和结构体类型的异同2.2.1类和对象的关系2.1节已经说明了什么是对象。C++中对象的类型称为类(class)。类代表了某一批对象的共性和特征。类是对象的抽象,而对象是类的具体实例。正如结构体类型与结构体变量的关系一样,(先声明一个结构体类型,然后用它定义结构体变量)在C++中也是先声明一个类类型,然后用它定义同类型的对象。对象是类类型的一个变量。类是抽象的,不占用内存空间。对象是具体的,要占用内存空间。2.2.2声明类类型类是要用户自己定义的类型,如果程序里要用类类型,程序员必须自己根据需要声明,也可以使用别人已设计好的类。声明一个类类型与声明一个结构体类型相似。structstudent{intnum;charname[20];charsex;};studentst1,st2;•classstudent•{•private:•intnum;•stringname;•charsex;•public:•voidsetdata()•{cinnum;cinname;cinsex;}•voiddisplay()•{coutnumendl;coutnameendl;•coutsexendl;•};•};•studentst1,st2;成员变量(数据成员,属性)成员函数(方法)类定义格式:class类名{private:私有成员声明public:公有成员声明protected:保护成员声明};class是保留字,声明类类型类名:按标识符取名。private、public、protected也是保留字,是成员访问限定符,其后必须跟冒号。其含义后面再解释。在类声明的}后如不直接定义对象就必须跟分号。2.2.3定义对象1.先声明类类型,然后再定义对象在声明类类型后,像定义变量一样定义对象。(1)class类名对象名表例:classstudentst1,st2;(2)类名对象名表例:studentst1,st2;2.在声明类类型的同时定义对象class类名{private:…public:…}对象名表;classstudent{intnum;stringname;charsex;public:voidsetdata(){cinnum;cinname;cinsex;}voiddisplay(){coutnumendl;coutnameendl;coutsexendl;}}st1,st2;3.不出现类名,直接定义对象class{private:…public:…}对象名表;这种方法在C++中虽然是合法的,但不提倡使用。在面向对象程序设计和C++程序中,类的声明和类的使用是分开的,类并不只为一个程序服务,人们常把一些常用的功能封装成类,并放在类库中。在实际程序开发中一般采用第一种方法,在小型程序中或声明的类只用于本程序时,也可采用第二种方法。在定义对象后,编译程序在编译时会为对象分配内存空间,存放对象的成员。2.2.4类和结构体类型的异同C++允许用struct定义一个类类型,为什么C++要这样做?这是设计C++语言时规定的一项原则:C++必须兼容C,让C程序不用修改就能在C++环境中使用。两种定义方法还是有区别的:用class声明的类如果不带成员访问限定符,所有成员默认限定为private;用struct声明的类如果不带成员访问限定符,所有成员默认限定为public。2.3类的成员函数在声明类时,必须定义访问类数据成员的函数,称之类的成员函数(方法)。•2.3.1在类内定义成员函数•2.3.2在类外定义成员函数•2.3.3内置函数•2.3.4成员函数的存储方式2.3.1在类内定义成员函数classstudent{intnum;stringname;public:voiddisplay(){coutnumendl;coutnameendl;coutsexendl;}};2.3.2在类外定义成员函数C++允许在类内声明成员函数的原型,然后在类外定义成员函数。格式类型类名::函数名(形参表){成员声明}classstudent{intnum;stringname;charsex;public:voidsetdata();voiddisplay();};voidstudent::setdata(){cinn