《面向对象编程技术第七章派生与继承优秀PPT.ppt》由会员分享,可在线阅读,更多相关《面向对象编程技术第七章派生与继承优秀PPT.ppt(53页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、面向对象编程技术第七章派生与继承第一页,本课件共有53页本章主要内容本章主要内容1.类的继承与派生的提出2.派生类的定义与相关概念3.三种基本继承方式4.派生类的构造与析构函数5.派生类的成员标示与访问6.虚基类7.赋值兼容规则第二页,本课件共有53页类的继承与派生的提出类的继承与派生的提出问题:问题:1.我会使用windows98,我需要重新学习XP操作系统吗?2.我定义了一个描述点的类,如何在定义一个描述矩形的类?现实思维模式现实思维模式.WH事物发展有事物发展有其延续性!其延续性!第三页,本课件共有53页类的继承与派生的提出类的继承与派生的提出继承的目的继承的目的:实现数据、代码的重用。
2、派生的目的派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有数据、代码进行改造。返返 回回第四页,本课件共有53页派生类的定义与相关概念派生类的定义与相关概念定定义义格格式式:class 派生类名:继承方式1 基类名1,继承方式n 基类名n成员声明;注:继承方式注:继承方式1.公有继承public2.私有继承private3.保护继承protected1.保持已有类的特性而构造新类的过程称为保持已有类的特性而构造新类的过程称为继承继承。2.在已有类的基础上新增自己的特性而产生新类的过程称为在已有类的基础上新增自己的特性而产生新类的过程称为派生派生。3.被继承的已有类称
3、为被继承的已有类称为基类基类(父类)。(父类)。4.派生出的新类称为派生出的新类称为派生类派生类(子类子类)。5.直接父类、直接父类、直接直接子类;间接父类、子类;间接父类、间接间接子类子类第五页,本课件共有53页派生类的定义与相关概念派生类的定义与相关概念派生(继承)的内部实现过程:派生(继承)的内部实现过程:添加新成员添加新成员 吸收除构造、析构吸收除构造、析构函数外基类成员函数外基类成员 改造基类成员改造基类成员第六页,本课件共有53页派生类的定义与相关概念派生类的定义与相关概念描述平面的一个点 矩形定义简单实例:简单实例:class pointpublic:point(int a,in
4、t b)x=a,y=b;int getx()int gety()void moveto(int a,int b)private:int x,int y;class rectangle:public pointpublic:public retangle(int x,int y,int width,int heigth):point(x,y)w=width;h=height;privated:int w,h;第七页,本课件共有53页派生类的定义与相关概念派生类的定义与相关概念基类与派生类的对应关系基类与派生类的对应关系:1.单继承:派生类只从一个基类派生。2.多继承:派生类从多个基类派生。3.多
5、重派生:由一个基类派生出多个不同的派生类。4.多层派生:派生类又作为基类,继续派生新的类。第八页,本课件共有53页简化的继承体系图简化的继承体系图返返 回回第九页,本课件共有53页三种基本继承方式三种基本继承方式1.公有继承公有继承(public)1)基类的public和protected成员的访问属性在派生类中保持不变;基类的private成员不可访问(类内类内)2)派生类的对象只能访问基类的public成员(类外类外)第十页,本课件共有53页class Apublic:int x;A(int a,int b)x=a;u=b;void prt()coutpublic x=:xendl;pri
6、vate:int u;举例举例 第一步:定义基类:第一步:定义基类:第十一页,本课件共有53页举例举例 第二第二 步:定义派生类步:定义派生类class B:public Apublic:B(int a,int b,int c):A(a,b)y=c;int y;void prt()coutA:x=:A:xendl;A:prt();/cout private base A:u=A:uendl;cout B:y=:yendl;此行错误!此行错误!第十二页,本课件共有53页举例举例 第三步:使用派生类第三步:使用派生类void main()B b(1,2,3);b.prt();/coutb.uend
7、l;运行结果:运行结果:A:x=:1public x=:1 B:y=:31Press any key to continueError!不可直接输出u.第十三页,本课件共有53页1)派生类中:基类public和protected成员变成private成员;基类private成员不可访问。2)通过派生类的对象不能访问基类中的任何成员2.私有继承私有继承(private)如何理解?类外的问题第十四页,本课件共有53页class Apublic:int x;A(int a,int b)x=a;u=b;void prt()coutpublic x=:xendl;private:int u;举例举例 第
8、一步:定义基类:第一步:定义基类:第十五页,本课件共有53页举例举例 第二第二 步:定义派生类步:定义派生类class B:private Apublic:B(int a,int b,int c):A(a,b)y=c;int y;void prt()coutA:x=:A:xendl;A:prt();cout B:y=:yendl;第十六页,本课件共有53页举例举例 第三步:使用派生类第三步:使用派生类void main()B b(1,2,3);b.prt();/coutb.xendl;运行结果:运行结果:A:x=:1public x=:1 B:y=:31Press any key to con
9、tinue私有数据,不可直接输出b.第十七页,本课件共有53页3.保护继承保护继承(public)1)派 生 类 中:基 类 的public和 protected成 员变 成protected成员;基类的private成员不可访问2)派生类的对象不能访问基类中的任何成员第十八页,本课件共有53页protected 成员举例成员举例class A protected:int x;int main()A a;/a.X=5;错误第十九页,本课件共有53页protected 继承class Apublic:int x void show_private()coutprivate of As y=y;v
10、oid show_proteced()coutprotected of As z=z;private:int y;protected:int z;第二十页,本课件共有53页class B:protected Apublic:void out_base_public()coutx=:xendl;/void out_base_private()couty=:yendl;Error!void out_base_proteced()coutz=:zendl;void main()B b;/b.x=19;Errror/b.y=19;Error/b.z=19;Errorb.out_base_public(
11、);b.out_base_proteced();如何访问如何访问A中的中的X、y、z?如何输出如何输出A中的私中的私有成员有成员?间接的方式间接的方式第二十一页,本课件共有53页三种继承方式之间的比较三种继承方式之间的比较返返 回回第二十二页,本课件共有53页派生类的构造与析构函数派生类的构造与析构函数一、构造函数一、构造函数1.基类的构造函数不被继承,需要在派生类中自行声明2.初始化完成:1.基类成员:基类构造函数完成2.内嵌对象成员3.新增成员顺序的思考:顺序的思考:有它的现实有它的现实原形么?原形么?第二十三页,本课件共有53页格式:格式:派生类名:派生类名(参数总表):基类名1(参数)
12、,基类名2(参数),.基类名n(参数),内嵌对象1(参数)内嵌对象n(参数)本类成员初始化赋值语句;派生类的构造函数派生类的构造函数注意:注意:参数的顺序不重要参数的顺序不重要对比组合类的对比组合类的构造函数构造函数第二十四页,本课件共有53页构造函数的调用次序构造函数的调用次序1.调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)。2.调用成员对象的构造函数,调用顺序按照它们在类中声明的顺序。3.派生类的构造函数完成新增成员的初始化。注意注意:派生类的析构函数的调用次序与构造函数正:派生类的析构函数的调用次序与构造函数正好相反好相反为什么?第二十五页,本课件共有53页举例举例:
13、讨论构造函数的调用次序问题讨论构造函数的调用次序问题class B1/基类B1,构造函数有参数public:B1(int i)coutconstructing B1 iendl;class B2/基类B2,构造函数有参数public:B2(int j)coutconstructing B2 jendl;class B3/基类B3,构造函数无参数public:B3()coutconstructing B3*endl;第二十六页,本课件共有53页class C:public B2,public B1,public B3 public:C(int a,int b,int c,int d):B1(a)
14、,memberB2(d),memberB1(c),B2(b)private:B1 memberB1;B2 memberB2;B3 memberB3;void main()C obj(1,2,3,4);认真思考并回答其输出结果?第二十七页,本课件共有53页constructing B2 2constructing B1 1constructing B3*constructing B1 3constructing B2 4constructing B3*Press any key to continue第二十八页,本课件共有53页对构造函数调用的讨论对构造函数调用的讨论1.基类采用缺省构造函数时:
15、派生类构造函数可以调用基类缺省构造函数。2.基类声明带形参的构造函数时,派生类传递参数给基类构造函数,完成基类成员的初始化1.自定义缺省构造函数:1.无参数 2.带缺省值2.系统默认构造函数两种情形两种情形第二十九页,本课件共有53页二、析构函数二、析构函数1.析构函数也不被继承,派生类自行声明2.声明方法与一般(无继承关系时)类的析构函数相同3.不需要显式地调用基类的析构函数,系统会自动隐式调用和组合类相似第三十页,本课件共有53页二、析构函数二、析构函数1.析构函数的调用次序与构造函数相反 2.自定义析构函数主要完成动态分配内存对象的释放第三十一页,本课件共有53页举例:举例:class
16、B1/基类B1声明public:B1(int i)coutconstructing B1 iendl;B1()coutdestructing B1 endl;class B2/基类B2声明public:B2(int j)coutconstructing B2 jendl;B2()coutdestructing B2 endl;第三十二页,本课件共有53页class B3/基类B3声明public:B3()coutconstructing B3*endl;B3()coutdestructing B3 endl;class C:public B2,public B1,public B3public
17、:C(int a,int b,int c,int d):B1(a),memberB2(d),memberB1(c),B2(b)private:B1 memberB1;B2 memberB2;B3 memberB3;第三十三页,本课件共有53页void main()C obj(1,2,3,4);输出结果:输出结果:Constucting B2 2Constucting B1 1Constucting B3*Constucting B1 3Constucting B2 4Constucting B3*Destructing B3Destructing B2Destructing B1Destruc
18、ting B3Destructing B1Destructing B2返返 回回第三十四页,本课件共有53页派生类的成员标示与访问派生类的成员标示与访问问题:问题:1.当派生类与基类中有相同成员时,如何标示与访问不同类中定义的成员?第三十五页,本课件共有53页举例:举例:class B1 public:int nV;void fun();class D1:public B1 public:int nV;void fun()如何访问如何访问D1类中、对象中成员?类中、对象中成员?看下页第三十六页,本课件共有53页派生类的成员标示与访问派生类的成员标示与访问同名覆盖原则同名覆盖原则当派生类与基类中
19、有相同成员时:1.若未强行指名,则通过派生类对象使用的是派生类中的同名成员。2.如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定。第三十七页,本课件共有53页void main()D1 d1;d1.nV=1;/对象名.成员名标识,访问D1类成员,同名覆盖d1.fun();d1.B1:nV=2;/作用域分辨符标识,访问基类B1成员d1.B1:fun();第三十八页,本课件共有53页派生类的成员标示与访问派生类的成员标示与访问消除二义性消除二义性 2.当多个直接基类中都从某一间接基类继承共同成员时如何标示和访问?(参见下页图)(参见下页图)问题:问题:问题越来越问题越来越复杂啦!复杂
20、啦!看下页第三十九页,本课件共有53页Class B0Public:Int nvVoid fun()class B1:public B0public:int nV1;void fun1();class B2:public B0 public:int nV2;void fun2();class D1:public B1,public B2 public:int nV;void fun*()第四十页,本课件共有53页派生类的成员标示与访问派生类的成员标示与访问解决解决二义性问题通过直接基类,使用作用域运算符来访问不同类中的成员参照上页图示参照上页图示 D1.B1:nv=1;D1.B2:nv=2;声
21、明虚基类(下节介绍)返返 回回第四十一页,本课件共有53页虚基类虚基类1.虚基类的引入:用于直接基类有共同基类的场合,2.防止多次初始化基类成员,实现维护一份拷贝3.声明:继承时以virtual修饰说明基类例:class B1:virtual public B注意:在第一级继承时就要将共同基类设计为虚基类。注意:在第一级继承时就要将共同基类设计为虚基类。下页举例第四十二页,本课件共有53页虚基类举例:虚基类举例:class B0/声明基类B0public:/外部接口int nV;void fun()coutMember of B0endl;class B1:virtual public B0
22、/B0为虚基类public:/新增外部接口int nV1;class B2:virtual public B0 /B0为虚基类派生B2类 public:/新增外部接口int nV2;第四十三页,本课件共有53页class D1:public B1,public B2/派生类D1声明 public:/新增外部接口int nVd;void fund()coutMember of D1endl;存储映象存储映象虚基虚基类类第四十四页,本课件共有53页void main()/程序主函数 D1 d1;/声明D1类对象d1d1.nV=2;/使用直接基类数据成员d1.fun();/使用直接基类函数成员使之虚
23、的思想使之虚的思想第四十五页,本课件共有53页虚基类及其派生类构造函数虚基类及其派生类构造函数1.建立对象的类称为最远派生类2.虚基类成员由最远派生类构造函数通过虚基类构造函数进行初始化第四十六页,本课件共有53页虚基类及其派生类构造函数虚基类及其派生类构造函数3.派生类在构造函数的成员初始化表中调用虚基类的构造函数。否则调用该虚基类的缺省构造函数4.C保证最远(当前)派生类的构造函数调用虚基类的构造函数,忽略其它父类对虚基类构造函数的调用避免多次构造第四十七页,本课件共有53页class B0/声明基类B0 public:/外部接口 B0(int n)nV=n;int nV;void fun
24、();class B1:virtual public B0 public:B1(int a):B0(a)int nV1;class B2:virtual public B0 public:B2(int a):B0(a)int nV2;直接基类与间接基类直接基类与间接基类定义定义第四十八页,本课件共有53页class D1:public B1,public B2public:D1(int a):B0(a),B1(a),B2(a)int nVd;void fund()coutMember of D1endl;void main()D1 d1(9);d1.nV=2;d1.fun();派生类定义派生类
25、定义返返 回回第四十九页,本课件共有53页赋值兼容原则赋值兼容原则一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:1.派生类的对象可以被赋值给基类对象2.派生类的对象可以初始化基类的引用3.指向基类的指针也可以指向派生类的对象对比类型转换在Vc等可视化开发工具中大量使用!第五十页,本课件共有53页举例举例:class B0/基类B0声明 public:void display()coutB0:display()endl;class B1:public B0 public:void display()coutB1:display()endl;class D1:publi
26、c B1public:void display()coutD1:display()display();/对象指针-成员名 第五十一页,本课件共有53页void main()/主函数B0 b0;/声明B0类对象B1 b1;/声明B1类对象D1 d1;/声明D1类对象B0*p;/声明B0类指针p=&b0;/B0类指针指向B0类对象fun(p);p=&b1;/B0类指针指向B1类对象 B0&b0ref=b1;/用派生类的对象初始化基类对象的引用fun(p);p=&d1;/B0类指针指向D1类对象fun(p);返返 回回第五十二页,本课件共有53页组合类的构造函数调用组合类的构造函数调用构造函数调用顺序:构造函数调用顺序:若调用缺省构造函数(即无形参的),则内嵌对象的初始化也将调用相应的缺省构造函数。内嵌对象的构造函数声明顺序声明顺序调用本类的构造函数调用本类的析构函数内嵌对象的构造函数构造:构造:析构:析构:返返 回回第五十三页,本课件共有53页