《继承与组合》PPT课件.ppt

上传人:牧羊曲112 文档编号:5568489 上传时间:2023-07-29 格式:PPT 页数:81 大小:399.50KB
返回 下载 相关 举报
《继承与组合》PPT课件.ppt_第1页
第1页 / 共81页
《继承与组合》PPT课件.ppt_第2页
第2页 / 共81页
《继承与组合》PPT课件.ppt_第3页
第3页 / 共81页
《继承与组合》PPT课件.ppt_第4页
第4页 / 共81页
《继承与组合》PPT课件.ppt_第5页
第5页 / 共81页
点击查看更多>>
资源描述

《《继承与组合》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《继承与组合》PPT课件.ppt(81页珍藏版)》请在三一办公上搜索。

1、继承与组合,第八章,2,8.1 继承的概念,自行车,3,4,5,6,继承的概念,7,现实世界中,组织概念常使用继承来构成一种层次结构,描述的是IS-A关系。例如:苹果是一种水果;汽车是一种交通工具等。在IS-A关系中,每个概念都具有其上一层概念所有的特性,同时又具有自身的特殊性。,8,生物类,动物类,植物类,微生物类,脊椎动物类,其它动物类,哺乳动物类,其它脊椎动物类,灵长动物类,其它动物类,人 类,狒狒类,其它灵长动物类,9,继承,继承是允许重用现有类来构造新类的特性。,基类,方法和属性,在面向对象程序设计中:,10,继承的优点,代码的可重用性类库重定义基类的成员函数向派生类添加新成员不需要

2、了解核心技术的细节,11,一、基本概念1、基类、派生类以原有的类为基础产生新类,在这个过程中原有的类称为基类,新类称为派生类。汽车类派生出卡车类。在此过程中,我们称汽车类为基类,卡车类为汽车类的派生类。,8.2 C+中的继承,12,注意:,派生类的声明必须指定基类的名称class Manager:public Employee任何类都能用作基类基类分为两种类型直接基类间接基类,13,例1:,处理某企业中雇员的程序,使用一个箭头从派生类指向基类表示派生类引用基类的函数和数据,而基类没有访问派生类的权限,14,例2:定义基类shape,class shape private:int m_x,m_y

3、;/位置 char m_color;/颜色public:void setposition(int x,int y);void setcolor(char color);int getx();int gety();char getcolor();,15,定义派生类(等边三角形类),class Triangle:public Shape public:Triangle(int x,int y,char color=R,float slen=1);float GetSideLength()const;void SetTriangle(int x,int y,char color,float slen

4、);void Draw();private:float m_SideLength;,派生新类:circle 圆形rectangle 矩形triangle 三角形,基类也称为父类派生类也称为子类,shape,circle,rectangle,triangle,17,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。,2、C+支持的继承形式,18,单一继承,class A;class B:public A;,将类之间的相似性质联系起来单一继承是从现有基类创建新类的过程,19,多级继承,class A;class B:public A

5、;class C:public B;,20,直接基类和间接基类,直接基类class A;class B:public A/A是B的直接基类;间接基类class A;class B:public A;class C:public B/A是C的间接基类;,21,层次继承,class A;class B:public A;class C:public A;class D:public C;class E:public C;,22,多重继承,class A;class B;class C:public A,public B;,23,3、继承访问控制,派生类的函数能够访问基类的保护和公有成员派生类的对象

6、公有派生的类的对象能够访问基类的公有成员私有和保护派生的类的对象不能访问基类的任何成员,24,派生类的定义格式,class 派生类名:继承方式 基类名1,继承方式 基类名n public:/派生类公有成员 private:/派生类私有成员,25,(1)继承方式,26,注意:,派生类不能访问基类的私有成员公有继承不改变基类成员的访问级别基类的另外两种访问级别使得所有继承的成员与基类成员(私有基类的私有成员或保护基类的保护成员)属于相同的访问级别,27,(2)可访问性,类成员总是能够被它们自己的类的方法访问继承类能访问基类的公有或保护成员公有成员可以在任何地方被访问,28,(3)实例,例:程序清单

7、8-1,29,4、继承的语法,继承的定义格式为:class 派生类名:继承方式1 基类名1,继承方式2 基类名2,派生类新定义成员;,30,*程序演示,类Person、类Student,31,二、继承中的构造函数和析构函数,先调用基类的构造函数,然后调用派生类的构造函数class Baseprotected:int a;public:Base()a=0;/默认构造函数 Base(int c)a=c;/单参数构造函数;class Derived:public Basepublic:Derived():Base()/默认构造函数 Derived(int c):Base(c)/单参数构造函数;,32

8、,当声明派生类的对象时,Derived obj;它将会首先调用基类的构造函数,然后调用派生类的构造函数基类构造函数是在派生类构造函数之后指定的,使用冒号分隔Derived():Base(),33,在派生类的构造函数调用中显式选择基类的构造函数Derived obj1(20);调用基类中的相应构造函数Derived(int c):Base(c);,派生类的对象的数据结构是由基类中说明的数据成员和派生类中说明的数据成员共同构成。将派生类的对象中由基类中说明的数据成员和操作所构成的封装体称为基类子对象,它由基类中的构造函数进行初始化。构造函数不能被继承,对派生类必须重新定义构造函数。在声明一个派生类

9、对象时,系统首先要通过派生类的构造函数调用基类的构造函数,对基类成员初始化;然后对派生类中新增的成员初始化。,35,程序清单8-2、8-3,36,继承中的析构函数,调用顺序与构造函数的调用顺序相反首先调用派生类的析构函数,然后调用基类的析构函数只有派生类的构造函数通过动态内存管理分配了内存空间时才需要定义析构函数如果派生类的构造函数没有动态内存分配,那么派生类的析构函数可以是一个空函数,37,程序清单8-4,38,*程序演示,类Car、类SportCar,39,应用实例(多继承),日期和时间,40,日期和时间,建立三个类,一个为日期类Date,一个为时间类Time,另一个为上面两个类的派生类D

10、ateTime。例如:#include#include#include typedef char string8080;class Datepublic:Date()Date(int y,int m,int d)SetDate(y,m,d);,void SetDate(int y,int m,int d)Year=y;Month=m;Day=d;void GetStringDate(string80,将参数表中所提供的各个表达式的值,按中所指定的格式,复制到由所指定的字符数组中,class Timepublic:Time()Time(int h,int m,int s)SetTime(h,m,

11、s);void SetTime(int h,int m,int s)Hours=h;Minutes=m;Seconds=s;void GetStringTime(string80,class TimeDate:public Date,public Timepublic:TimeDate():Date(),Time()TimeDate(int y,int mo,int d,int h,int mi,int s):Date(y,mo,d),Time(h,mi,s)void GetStringDT(string80,派生类构造函数,本身无数据成员,函数体为空,无参构造函数,有参构造函数,void m

12、ain()TimeDate date1,date2(1998,8,12,12,45,10);string80 DemoStr;date1.SetDate(1998,8,7);/来自于Date基类date1.SetTime(10,30,45);/来自于Time基类date1.GetStringDT(DemoStr);/自身成员函数cout“The date1 date and time is”DemoStrendl;date1.GetStringDate(DemoStr);/来自于Date基类cout“The date1 date is”DemoStrendl;date1.GetStringTi

13、me(DemoStr);/来自于Time基类cout“The date1 time is”DemoStrendl;date2.GetStringDT(DemoStr);/自身成员函数cout“The date2 date and time is”DemoStrendl;,执行该程序输出结果如下:The date1 date and time is 1998/8/7;10:30:45The date1 date is 1998/8/7The date1 time is 10:30:45The date2 date and time is 1987/8/12;12:45:10,46,三、派生类中继

14、承成员函数的重定义,继承的目的是在一般性的类的基础上生成具有特殊性的类。可能出现重新定义原有函数以实现不同功能的情况,称为函数的重定义。并且派生类的成员函数可以和基类中的成员函数同名用基类的对象调用函数时,将调用基类的函数使用派生类的对象时,将调用派生类的函数派生类的成员函数要调用基类的同名函数,必须使用作用域解析操作符,47,例:调用成员函数,class Baseprotected:int ss;public:Base();Base(int a)ss=a;int func()return ss;,class Derived:public Base public:Derived();Deriv

15、ed(int b)ss=b;int func()return Base:func();void main()Base b1(10);/基类的对象 b1.func();/调用基类的func()Derived a1;/派生类的对象 a1.func();/调用派生类的func(),48,习题(1),#include class B private:int i;public:void set_i(int n)i=n;int get_i()return i;class D:public B int j;public:void set_j(int n)j=n;int nul()return j*get_i

16、();,49,int main()D ob;ob.set_i(10);ob.set_j(4);coutob.nul();return 0;,如果 class D:public B;继承访问控制方式改为:class D:private B;或 class D:protect B;则D类中继承的成员、ob对象的访问控制是什么情况?,习题(2),class Base private:int b_number;public:Base()Base(int i):b_number(i)int get_number()return b_number;void print()cout b_number end

17、l;class Derived:public Base private:int d_number;public:Derived(int i,int j):Base(i),d_number(j);void print()cout get_number();cout d_number endl;,52,int main()Base a(2);Derived b(3,4);cout a is;a.print();cout b is;b.print();cout base part of b is;b.Base:print();return 0;,53,习题(3),class b int a;publ

18、ic:int get()return a;;class d:b int xb;public:void make()xb=get()+10;;,int main()b ob1;d ob2;ob2.make();ob2.get();,习题(4),class basepublic:base()coutconstructing base classendl;base()coutdestructing base classendl;class subs:public base public:subs()coutconstructing sub classendl;subs()coutdestructin

19、g sub classendl;void main()subs s;,注意:在单继承情况下,首先调用基类的构造函数,随后调用派生类的构造函数,析构函数的调用顺序则正好相反。,55,8.3 组合,一、组合的语法与图形表示组合是一种通过创建一个组合了其他对象的类来获得新功能的软件重用方法。(描述的是类之间的HAS-A关系)例如:一个汽车的属性中包含了车轮类的对象。,56,例:,class Wheel;class Car public:private:int weight;int speed;Wheel wheel4;,57,图形表示法:,58,二、组合的构造与析构函数,问题:当一个对象作为另一个类

20、对象的数据成员时,构造函数如何被调用?分析:构造函数的调用次序是:(1)按类声明中嵌入对象出现的次序,分别调用个嵌入对象的构造函数(2)执行本类的构造函数,59,程序清单8-5,60,习题(5),#include class base int n;public:base(int a)coutconstructing base classendl;n=a;coutn=nendl;base()coutdestructing base classendl;,class subs:public base base bobj;int m;public:subs(int a,int b,int c):ba

21、se(a),bobj(c)coutconstructing sub cassendl;m=b;coutm=mendl;subs()coutdestructing sub classendl;void main()subs s(1,2,3);,62,输出为:,注意:当派生类中含有对象成员时,构造函数的调用顺序如下:1)基类的构造函数2)对象成员的构造函数3)派生类的构造函数析构函数的调用顺序与之相反,constrcuting base class n=1 constructing base class n=3 constructing sub class m=2 destructing sub

22、class destructing base class destructing base class,63,组合的实例,程序8-6,64,8.4 继承与组合的比较,继承描述的是一种一般性和特殊性的关系,使用继承可创建已存在类的特殊版本。组合描述的是一种组成关系,使用组合可用已存在的类组装新的类。继承和组合是两种重要的软件重用方法。,65,8.5 多重继承与重复继承,一、多重继承,可看作是单继承的扩展。,66,示例:,程序8-7,67,二、多重继承的构造函数,一般格式为:派生类名(参数表):初始化列表 派生类构造函数体;构造函数不被继承,基类的构造函数由派生类的构造函数调用,而多重继承下必须同

23、时负责该派生类所有基类构造函数的调用。同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数。,68,派生类名(参数表):基类名1(实参表1),基类名2(实参表2)派生类构造函数体;,69,先执行所有基类的构造函数再执行子对象类的构造函数(若有)再执行派生类本身的构造函数注意:同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化表的各项顺序无关。,派生类构造函数的调用顺序是:,#include class B1 public:B1(int i)b1=i;cout“constructor B1.”Iendl;void print()

24、coutb1endl;private:int b1;class B2 public:B2(int i)b2=i;cout“constructor B2.”Iendl;void print()coutb2endl;private:int b2;class B3 public:B3(int i)b3=i;cout“constructor B3.”Iendl;int getb3 return b3;private:int b3;,class A:public B2,public B1 public:A(int i,int j,int k,int l):B1(i),B2(j),bb(k)a=l;cou

25、t“constructor A.”I endl;void print()B1:print();B2:print();couta“,”bb.getb3()endl;private:int a;B3 bb;void main()A aa(1,2,3,4);aa.print();,72,运行结果:constructor B2.2constructor B1.1constructor B3.3constructor A.4124,3,73,三、多重继承中存在的问题:名字冲突,在多重继承下,若多个基类具有相同的成员名,可能造成对基类中该成员的访问出现不是唯一的情况,则称为对基类成员访问的二义性。,int

26、 main()DeviceNew device(0.7,3,false,10,250,80);cout“The weight of the device:”device.getWeight();device.showPower();device.showProperty();return 0;,74,1、使用相应的类名来标识device.Device1:showPower();2、在派生类中重定义有名称冲突的成员void showPower()Device1:showPower();Device2:showPower();,消除二义性有两种方法:,75,当一个派生类从多个基类派生,而这些基类又

27、有一个共同的基类,会出现重复继承的情形。,四、重复继承,76,class A public:int a;class B1:public A private:int b1;class B2:public A private:int b2;class C:public B1,public B2 public:int f();private:int c;c1.a;c1.A:a;/存在二义性,也会出现二义性问题:,77,程序清单8-8,78,1、采用作用域操作符(:)明确选择是哪个副本 中的数据 c1.B1:a;c1.B2:a;2、使用虚基类class B1:virtual public A priv

28、ate:int b1;class B2:virtual public A private:int b2;这样派生类的存储空间中只保留被重复继承的祖先类的一个对象副本。(程序清单8-9),消除二义性有两种方法:,79,虚基类的说明,在上例中,由类A,类B1和类B2以及类C组成了类继承的层次结构。在该结构中,类C的对象将包含两个公共基类A的子对象。若只想使公共基类在派生类中只产生一个基类子对象,则必须将该基类设定为虚基类。其真正目的是为了解决二义性问题。说明格式为:class 派生类名:virtual 继承方式 基类名;,如:class A public:int a;class B1:virtual public A private:int b1;class B2:virtual public A private:int b2;class C:public B1,public B2 public:int f();private:int c;则:c1.a;c1.A:a;c1.B1:a;c1.B2:a;,81,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号