清华大学出版社钱能课件.ppt

上传人(卖家):晟晟文业 文档编号:4506601 上传时间:2022-12-15 格式:PPT 页数:59 大小:922.50KB
下载 相关 举报
清华大学出版社钱能课件.ppt_第1页
第1页 / 共59页
清华大学出版社钱能课件.ppt_第2页
第2页 / 共59页
清华大学出版社钱能课件.ppt_第3页
第3页 / 共59页
清华大学出版社钱能课件.ppt_第4页
第4页 / 共59页
清华大学出版社钱能课件.ppt_第5页
第5页 / 共59页
点击查看更多>>
资源描述

1、清华大学出版社 钱 能讲师:曹晓丽16.1 继承的概念16.2 继承的工作方式16.3 派生类的构造16.4 继承与组合16.5 多态性16.6 多态的思考方式16.7 不恰当的虚函数16.8 虚函数的限制16.9 虚函数的限制16.10 类的冗余16.11 客服冗余带来的问题16.12 类的分解16.13 抽象类16.14 有抽象类派生具体类16.15 纯虚函数的需要小结教学目标:能利用继承现有的类建立新类理解继承如何提高软件的重用性理解多态性对于继承的意义掌握多态的工作原理理解抽象类和具体类的区别学会运用纯虚函数基类(父类)派生类(父类)祖先类继承是我们理解事物,解决问题的方法;通过继承,

2、可以从已有的类派生出新类,新类继承父类的属性和操作,并在已有类的基础上新增自己的属性和操作,剔除那些不适合于其用途的继承下来的操作;被继承的已有类称为基类(父类),派生出的新类称为派生类(子类);继承可以减少代码的冗余性,实现代码的重用,并且通过作少量的修改,满足不断变化的具体应用要求,提高程序设计的灵活性;派生类的定义class 派生类名:继承方式 基类名1,成员定义;基类与派生类的关系是相对的;多继承:一个派生类有多个直接基类;单继承:一个派生类只有一个直接基类;例如:现有一个学生类Student,要增加研究生类GraduateStudent。由于研究生除了他自己特有的性质外,具有学生的所

3、有性质,所以我们用继承的方法来重用学生类。Ch16_1.cppclass Student /;class GraduateStudent:public Student /;StudentGradusteStudent#include#includeclass Advisor int noOfMeeting;class Studentpublic:Student(char*pName=no name)strncpy(name,pName,sizeof(name);average=semesterHours=0;void addCourse(int hours,float grade)averag

4、e=(semesterHours*average+grade);/总分 semesterHours+=hours;/总修学时 average/=semesterHours;/平均分 int getHours()return semesterHours;float getAverage()return average;void display()cout name=name,hours=semesterHours ,average=average endl;protected:char name40;int semesterHours;float average;class GraduateSt

5、udent:public Studentpublic:getQualifier()return qualifierGrade;protected:Advisor advisor;int qualifierGrade;void main()Student ds(Lo lee undergrade);GraduateStudent gs;ds.addCourse(3,2.5);ds.display();gs.addCourse(3,3.0);gs.display();运行结果:name=Lo lee undergrade,hours=3,average=0.833333name=“no name,

6、hours=3,average=1继承方式继承方式指定了派生类成员以及类外对象对继承来的成员的访问权限。三种继承方式:公有继承(public);保护继承(protected);私有继承(private);派生类不继承基类的构造函数和析构函数,但是能调用基类的构造函数和析构函数;派生类的构造函数总是先调用基类的构造函数来初始化派生类中的基类成员,再进行派生类中成员的初始化;派生类构造函数的定义中,要提供基类构造函数所需要的参数。如果派生类没有用户自定义的构造函数,执行其默认构造函数时,首先调用基类的构造函数;析构函数的调用顺序和构造函数的调用顺序相反;子类的构造函数要有一个默认的父类的构造函数对

7、应class Basepublic:Base(int i);Base();void print();private:int a;class Derive:public Basepublic:Derive(int i,int j);Derive();void print();private:int b;Base:Base(int i)a=i;cout Base constructor endl;Base:Base()cout Base destructor endl;void Base:print()cout a endl;Derive:Derive(int i,int j):Base(i)b=

8、j;cout Derive constructor endl;Derive:Derive()cout Derive destructor endl;void Derive:print()Base:print();cout b endl;:a(i)void main()Derive d(2,5);d.print();Base constructorDerive constructor25Derive destructorBase destructorclass Basepublic:Base();Base(int i);.;class Derive:public Basepublic:Deriv

9、e(int i,int j).;class Basepublic:Base()cout Base constructor endl;Base()cout Base destructor endl;void print();class Derive:public Basepublic:void set(int i)b=i;void print()cout b endl;private:int b;void main()Derive d;d.set(2);d.print();Base constructor2Base destructor组合:一个类的数据成员是另一个类的对象;继承和组合都利用了已

10、经定义的类,但是类之间关系上有差别;继承时子类享有父类的一切待遇,父类能出现的地方,子类同样可以出现,如汽车是车辆的子类,继承了车辆所有属性;而组合说明一个类只是另一个类的成员,不能代表类本身,汽车包含有一个马达,但马达不是汽车,汽车也不是马达。构造函数的调用顺序:调用基类构造函数;调用各成员对象的构造函数,调用顺序按照它们在类中声明的顺序。执行派生类的构造函数体中的内容;class Baseint a;public:Base(int i)a=i;cout Base constructor endl;Base()cout Base destructor endl;void print()cou

11、t a endl;class Memberint b;public:Member(int j)b=j;cout Member constructor endl;Member()cout Member destructor endl;void print()cout b endl;class Derive:public Baseint c;Member mem;public:Derive(int i,int j,int k):mem(j),Base(i)c=k;cout Derive constructor endl;Derive()cout Derive destructor endl;voi

12、d print()Base:print();mem.print();cout c endl;void main()Derive d(2,3,4);d.print();Base constructorMember constructorDerive constructor234Derive destructorMember destructorBase destructorclass Baseint a;public:Base(int i):a(i);class Derive:public Baseint b;public:Derive(int i):b(i*15),Base(b);void m

13、ain()Derive d(10);在程序中同一符号或名字在不同情况下具有不同解释的现象称为多态性。是指同一函数的多种行为。Early binding(编译时多态性):在程序编译阶段即可确定下来的多态性,主要通过使用重载机制获得;函数名相同,参数类型不同、个数不同,或返回值类型不同。Late binding(运行时多态性):必须等到程序动态运行时才可确定的多态性,主要通过虚函数实现;参数类型、个数、返回值类型必须相同。否则不能迟后联编。运行时多态性的优点运行时根据实际对象的类型,动态地决定应该使用虚函数的哪个版本,符合人们的习惯,实现了更高级更自然的抽象;进一步减少了信息冗余;显著提高了程序的

14、可重用性、可扩展性、可维护性;我们通常说的多态性是指运行时多态性。有时候,会遇到对象所属的类不能确定的情况,C+继承机制用一种称为多态性的技术解决上面的问题,为了指明某个成员函数具有多态性,用关键字virtual来标志其为虚函数。编译看见虚函数时,将其作为迟后联编来处理,保证运行时确定调用哪个虚函数。虚函数可以继承,所以子类中的虚函数前的virtual可以省略。class Basepublic:virtual void view()cout In Base!endl;class Derive:public Base public:void view()cout In Derive!endl;v

15、oid func(Base&b)b.view();void main()Base b1;func(b1);/调用Base的成员函数Derive d1;func(d1);/调用Derive的成员函数In Base!In Derive!n赋值兼容原则一个公有继承的派生类对象可以隐式转化为一个基类对象:用派生类的对象给基类对象赋值;用派生类的对象来初始化基类的引用;把派生类对象的地址赋值给指向基类的指针;把指向派生类对象的指针赋值给指向基类对象的指针;访问范围基类对象不能代替派生类对象;基类成员派生类成员如果虚函数在基类与子类中出现的仅仅是名字的相同,而参数类型不同,或返回值类型不同,即使写上了Vi

16、rtual,也不进行迟后联编,按同名函数重载处理。P360 ch16_4#include class Basepublic:virtual void fn(int x)cout In Base class,int x=x endl;class SubClass:public Basepublic:virtual void fn(float x)cout In SubClass,float x=x endl;void test(Base&b)int i=1;b.fn(i);float f=2.0;b.fn(f);void main()Base bc;SubClass sc;cout Callin

17、g test(bc)n;test(bc);cout Calling test(sc)n;test(sc);In Base!In Base!如果基类中的虚函数返回一个基类指针或返回一个基类的引用,子类中的虚函数返回一个子类指针或一个子类的引用,则C+将其视为同名虚函数而进行迟后联编。Ch16_5.cpp#include class Basepublic:virtual Base*afn()cout This is Base class.n;return this;class SubClass:public Basepublic:SubClass*afn()cout This is SubClas

18、s.n;return this;class SubClass:public Basepublic:SubClass*afn()cout This is SubClass.n;return this;void test(Base&x)Base*b;b=x.afn();void main()This is Base class.This is SubClass.Base bc;SubClass sc;test(bc);test(sc);定义虚函数,在类定义中函数原型之前加virtual;virtual只用来说明类定义中的原型,不能用在函数实现时;class Base public:virtual

19、void display();virtual void B0:display()/Errorcout“In Base!endl;虚函数在基类与派生类中的声明(包括函数名,返回值类型和参数表列)必须一样,才能实现运行时的多态;class Basepublic:virtual void fn1();virtual void fn2();virtual void fn3();class Derive:public Basepublic:void fn1();int fn2();void fn3(int);基类中定义了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数;只有类的非静态成员函数才能声

20、明为虚函数;内联函数不能是虚函数;构造函数不能是虚函数;析构函数通常是虚函数;动态绑定 成员函数调用中代码地址的确定非虚成员函数是根据指向对象的指针的类型静态地(在编译时)选择虚成员函数是动态(在运行时)解析的。根据对象的类型而不是根据指向对象的指针的类型来动态地(在运行时)选择使用虚函数,系统将使用动态绑定在程序设计中提供更强的功能和灵活性处理过程中占用一些开销两个类如果有很多相同的成员,可以将共同的特性分解到基类中。纯虚函数(pure virtual function):被标明为不具体实现的虚成员函数;纯虚函数的声明格式为:virtual 函数类型 函数名(参数表)=0;抽象类(abstr

21、act class):不能有实例对象的类,唯一的用途是被继承,一个抽象类至少具有一个虚函数;抽象类的作用抽象类为抽象和设计的目的而建立,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。派生类实现纯虚函数的参数要与父类纯虚函数声明的参数相同const double PI=3.1415926;class Shape2Dprotected:double BaseX,BaseY;public:Shape2D(double x,double y):BaseX(x),BaseY(y)virtual double Area(

22、)=0;class Circle:public Shape2Ddouble radius;public:Circle(double x,double y,double r):Shape2D(x,y),radius(r)double Area()return PI*radius*radius;class Rectangle:public Shape2Ddouble RectangleX,RectangleY;public:Rectangle(double x,double y,double l,double w):Shape2D(x,y),RectangleX(l),RectangleY(w)d

23、ouble Area()return(RectangleX-BaseX)*(RectangleY-BaseY);void main()Circle cir(1.0,1.0,5.0);double s1=cir.Area();couts1endl;Rectangle rect(2.0,0.0,6.0,7.5);double s2=rect.Area();couts2endl;78.539830Shape2D s3(0.0,0.0);/Error不能定义抽象类的对象,但可以声明抽象类的指针或引用。通过改变指针或引用的具体地址,指向相应的派生类的对象,以便实现运行时的多态;void PrintAre

24、a(Shape2D&s)couts.Area()endl;void main()Circle cir(1.0,1.0,5.0);Rectangle rect(2.0,0.0,6.0,7.5);PrintArea(cir);PrintArea(rect);派生类如果没有定义全部纯虚函数的操作,继承了部分纯虚函数,则仍然是抽象类。class Base.virtual void init()=0;virtual void print()=0;class Derive1:public Base.virtual void init().class Derive2:public Derive1.virtual void print().调用析构函数是为了释放由构造函数分配的内存空间如果基类的析构函数是非虚的,则不能用指向派生类的指针调用派生类的析构函数需要虚析构函数虚函数绑定到与对象所属的类,而不是与指针所对应的类派生类的实例总是包含一个基类的实例需要调用这两个类的析构函数以确保所有空间都被释放注意:构造函数不能是虚函数

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(清华大学出版社钱能课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|