12从过程化到面向对象类的定义及对象的使用继承多态性模板异常处理3抽象的过程面向对象的程序设计的特点4计算机的工作是建立在抽象的基础上。机器语言和汇编语言是对机器硬件的抽象高级语言是对汇编语言和机器语言的抽象现有抽象的问题:要求程序员按计算机的结构去思考,而不是按要解决的问题的结构去思考。当程序员要解决一个问题时,必须要在机器模型和实际要解决的问题模型之间建立联系。而计算机的结构本质上还是为了支持计算,当要解决一些非计算问题时,这个联系的建立是很困难的5为程序员提供了创建工具的功能解决一个问题时程序员首先考虑的是需要哪些工具创建这些工具用这些工具解决问题工具就是所谓的对象现有的高级语言提供的工具都是数值计算的工具6过程化的设计方法:从功能和过程着手输入圆的半径或直径利用S=πr2和C=2πr计算面积和周长输出计算结果面向对象的程序设计方法:需要什么工具。如果计算机能提供给我们一个称为圆的工具,它可以以某种方式保存一个圆,告诉我们有关这个圆的一些特性,如它的半径、直径、面积和周长。定义一个圆类型的变量,以他提供的方式将一个圆保存在该变量中,然后让这个变量告诉我们这个圆的面积和周长是多少以计算圆的面积和周长的问题为例7抽象的过程面向对象的程序设计的特点8代码重用:圆类型也可以被那些也需要处理圆的其他程序员使用实现隐藏:类的创建者创造新的工具类的使用者则收集已有的工具快速解决所需解决的问题这些工具是如何实现的,类的使用者不需要知道9继承:在已有工具的基础上加以扩展,形成一个功能更强的工具。如在学校管理系统中,可以形成如下的继承关系人教师学生教辅高级中级初级本科硕士博士实验室行政10多态性:当处理层次结构的类型时,程序员往往想把各个层次的对象都看成是基类成员。如需要对教师进行考核,不必管他是什么职称,只要向所有教师发一个考核指令。每位教师自会按照自己的类型作出相应的处理。如高级职称的教师会按高级职称的标准进行考核,初级职称的教师会按初级职称的标准进行考核。好处:程序代码就可以不受新增类型的影响。如增加一个院士的类型,它也是教师类的一个子类,整个程序不用修改,但功能得到了扩展。11从过程化到面向对象类的定义及对象的使用继承多态性模板异常处理12类的定义对象的使用对象的构造与析构常量对象与const成员函数静态数据成员与静态成员函数对象成员一个工具就是一种类型。为了与内置类型相区分,用户自己定义的类型成为类。一个类型包括两个方面在内存中如何保存该类型的数据对该类型可以做哪些操作,这些操作如何实现定义一个类也包括两部分数据成员成员函数14class类名{[private:]私有数据成员和成员函数public:公有数据成员和成员函数};15私有成员(private):只能由类的成员函数调用公有成员(public):类的用户可以调用的信息,是类对外的接口私有成员被封装在一个类中,类的用户是看不见的设计一个类,提供动态实型数组服务,该数组满足两个要求:可以任意指定下标范围;下标范围可在运行时确定;使用下标变量时会检查下标的越界。数组的保存数组需要一块保存数组元素的空间。这块空间需要在执行时动态分配。数组的下标可以由用户指定范围。因此,对每个数组还需要保存下标的上下界。数组操作给数组分配空间给数组元素赋值取某一个数组元素的值由于这个数组的存储空间是动态分配的,因此,还必须有一个函数去释放空间classDoubleArray{private:intlow;inthigh;double*storage;public:boolinitialize(intlh,intrh);boolinsert(intindex,doublevalue);boolfatch(intindex,double&value);voidcleanup();};19类的定义写在接口文件中,成员函数的实现写在实现文件中。某些简单的成员函数的定义可以直接写在类定义中。boolDoubleArray::initialize(intlow,inthigh){low=low;high=high;storage=newdouble[high-low+1];if(storage==NULL)returnfalse;elsereturntrue;}boolDoubleArray::insert(intindex,doublevalue){if(indexlow||indexhigh)returnfalse;storage[index-low]=value;returntrue;}boolDoubleArray::fatch(intindex,double&value){if(indexlow||indexhigh)returnfalse;value=storage[index-low];returntrue;}voidDoubleArray::cleanup(){delete[]storage;}22试定义一个有理数类,该类能提供有理数的加和乘运算。要求保存的有理数是最简形式。如2/6应记录为1/3。23保存有理数:保存一个有理数就是保存两个整数。有理数类的操作:加函数乘函数创建有理数的函数,用以设置有理数的分子和分母输出有理数函数化简函数访问权限设计:数据成员是私有的化简函数是内部调用的函数,与用户无关,因此也是私有的其他函数都是公有的24#ifndef_rational_h#define_rational_h#includeiostreamusingnamespacestd;classRational{private:intnum;intden;voidReductFraction();//将有理数化简成最简形式public:voidcreate(intn,intd){num=n;den=d;}voidadd(constRational&r1,constRational&r2);voidmulti(constRational&r1,constRational&r2);voiddisplay(){coutnum'/'den;}};#endif有理数类的定义25#includeRational.h“//add函数将r1和r2相加,结果存于当前对象voidRational::add(constRational&r1,constRational&r2){num=r1.num*r2.den+r2.num*r1.den;den=r1.den*r2.den;ReductFraction();}26voidRational::multi(constRational&r1,constRational&r2){num=r1.num*r2.num;den=r1.den*r2.den;ReductFraction();}voidRational::ReductFraction(){inttmp=(numden)?den:num;for(;tmp1;--tmp)if(num%tmp==0&&den%tmp==0){num/=tmp;den/=tmp;break;}}27类的定义对象的使用对象的构造与析构常量对象与const成员函数静态数据成员与静态成员函数对象成员28类与对象的关系:类型与变量的关系对象定义方法:直接在程序中定义某个类的对象存储类别类名对象列表;如定义两个DoubleArray类的对象arr1和数组arr2,可写成:DoubleArrayarr1,arr2[20];用动态内存申请的方法申请一个动态对象。Rational*rp;Rp=newRational;rp=newRational[20];deleteRp;或delete[]rp;29对象名.数据成员名或对象指针-数据成员名arr1.storage或rp-num对象名.成员函数名(实际参数表)或对象指针-成员函数名(实际参数表)arr1.insert()或rp-add()外部函数不能引用对象的私有成员intmain(){DoubleArrayarray;doublevalue;intlow,high,i;cout请输入数组的下标范围:;cinlowhigh;if(!array.initialize(low,high)){cout空间分配失败;return1;}DoubleArray类的应用for(i=low;i=high;++i){cout请输入第i个元素:;cinvalue;array.insert(i,value);}while(true){//数组元素的查找cout请输入要查找的元素序号(0表示结束):;cini;if(i==0)break;if(array.fatch(i,value))coutvalueendl;elsecout下标越界\n;}array.cleanup();return0;}32#includeiostreamusingnamespacestd;#includeRational.h//使用有理数类intmain(){intn,d;Rationalr1,r2,r3;//定义三个有理数类的对象计算两个有理数的和与积33cout请输入第一个有理数(分子和分母):;cinnd;r1.create(n,d);cout请输入第二个有理数(分子和分母):;cinnd;r2.create(n,d);r3.add(r1,r2);//执行r3=r1+r2r1.display();cout+;r2.display();cout=;r3.display();coutendl;r3.multi(r1,r2);//执行r3=r1*r2r1.display();cout*;r2.display();cout=;r3.display();coutendl;return0;}34请输入第一个有理数(分子和分母):16请输入第二个有理数(分子和分母):161/6+1/6=1/31/6*1/6=1/3635同类型的对象之间可以互相赋值,如两个有理数对象r1和r2,可以执行r1=r2;当一个对象赋值给另一个对象时,所有的数据成员都会逐位拷贝。上述赋值相当于执行r1.num=r2.numr1.den=r2.den36当定义一个对象时,系统会为对象分配空间,用于存储对象的数据成员。而类中的成员函数对该类的所有对象只有一份拷贝。那么对于类的成员函数,它如何知道要对哪个对象进行操作呢?每个成员函数都有一个隐藏的指向本类型的指针形参this,它指向当前调用成员函数的对象如对函数voidcreate(intn,intd){num=n;den=d;}经过编译后,实际函数为voidcreate(intn,intd){this-num=n;this-den=d;}37通常,在写成员函数时可以省略this,编译时会自动加上它们。如果在成员函数中要把对象作为整体来访问时,必须显式地使用this指针。这种情况常出现在函数中返回一个对调用函数的对象的引用,38类的定义对象的使用对象的构造与析构常量对象与const成员函数静态数据成员与静态成员函数对象成员39某些类的对象,必须在对它进行了初始化以后才能使用。对于某些类的对象在消亡前,往往也需要执行一些操作,做一些善后的处理。初始化和扫尾的工作给类的用户带来了额外的负担,使他们觉得类和内置类型还是不一样。用户希望使用类的对象就和使用内置类型的变量一样,一旦定义了,就能直接使用。用完了,由系统自动回收。40构造函数和析构函数是特殊的成员函数构造函数:对数据成员进行初始化。析构函数:执行与构造函数相反的操作,通常执行一些清理工作,如释放分配给