《计算机软件及应用继承doc资料.ppt》由会员分享,可在线阅读,更多相关《计算机软件及应用继承doc资料.ppt(47页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、计算机软件及应用继承如果一个派生类只从一个基类派生,称为单继承;如果一个派生类从多个基类派生,称为多重继承关于继承的几点说明:如果子类继承了父类,则子类自动具有父类的全部数据成员(数据结构)和成员函数(功能);但是,子类对父类成员的访问有所限制。子类可以定义自己的成员是数据成员和成员函数。基类、派生类或父类、子类都是“相对”的。一个类派生出新的类就是基类。派生类也可以被其他类继承,这个派生类同时也是基类。派生类的定义语法格式如下:class 派生类名:继承方式 基类名 新增私有成员声明语句列表public:新增公有成员声明语句列表protected:新增保护成员声明语句列表;例如:class
2、Book/定义基类Book private:int num;/书号float price;/定价int sellnum;/销售量 public:float sale()/计算销售额 return price*sellnum;class Book1:public Book/定义派生类Book1 private:char type;/定义图书类别,新增加的数据成员char name40;/书名,新增加的数据成员char publisher20;/出版社,新增加的数据成员 public:void show()/显示图书信息,新增加的成员函数 couttype:typeendl;coutname:na
3、meendl;coutpublisher:publisherendl;派生类的构成派生类中的成员包括两部分,一部分是从基类继承过来的成员,一部分是在声明派生类时新增加的成员,每一部分均包括数据成员和成员函数。派生类要继承基类的所有成员,对基类的继承方式不同,其访问属性也不同派生类可以在原有基类成员的基础上添加新的成员,也可以更改原有成员属性。若在派生类中声明一个与基类成员同名的新成员,该成员就会覆盖原有的成员;若声明的是同名函数,要保证函数的参数也完全相同【回顾】类中的成员的不同访问权限public公有成员:一个类的公有成员允许本类的成员函数、本类的对象、公有派生类的成员函数、公有派生类的对象
4、访问。private私有成员:一个类的私有成员只允许本类的成员函数访问。protected保护成员:具有私有成员和公有成员的特性,对其派生类而言是公有成员,对其他而言是私有成员。基类数据成员声明为保护的是有益的,派生类可以自由访问,外部不能访问,既实现了信息重用,又做到了信息隐藏。【例7.2】类的各种成员的访问权限。#includeclass A int i;/私有成员protected:/保护成员int j;void fn1()cout保护成员i=i j=jendl;public:/公有成员A(int x,int y)i=x;j=y;void fn2()/成员函数可以访问保护成员 cout公
5、有成员i=i j=jendl;fn1();void main()A x(21,63);x.fn2();执行结果:公有成员i=21 j=63保护成员i=21 j=63在主程序中只能访问公有成员,成员函数可以访问保护成员和私有成员,在例7.2中,只能由函数fn2()访问函数fn1(),不能在主程序中调用x.fn1()。派生类的继承方式继承方式决定了子类对父类的访问权限,有3种继承方式:private、public和protected,默认为private1公有继承【例79-1】当派生类的继承方式是公有继承(public)时,基类的public成员和protected成员的访问属性在派生类中保持不变
6、,基类的private成员被继承到派生类中仍是基类的private成员。2私有继承【例79-2】当派生类的继承方式是私有继承(private)时,基类的public成员和protected成员被继承到派生类中成为private成员,基类的private成员被继承到派生类中仍为private成员【例7.3】学校职工类的公有继承和私有继承。类people是基类,定义人的姓名、性别、身份号和对这3种数据的显示。类member私有继承people,定义了职工号、部门和信息显示,类member生成的对象不能直接访问类people中的任何成员。类worker公有继承类member,定义了岗位和信息显示,类
7、worker生成的对象可以直接访问类member中的公有成员。类teacher私有继承类member,定义了执教课程和信息显示,类teacher生成的对象不能直接访问类member中的任何成员。#include#includeclass peoplechar name10,sex;/姓名,性别long idnumber;/身份号码public:people(long num=0,char*n=,char s=m)/构造函数 idnumber=num;strcpy(name,n);sex=s;void p_show()cout人员:身份号=idnumber;cout姓名=name性别=sexen
8、dl;class member:private people/教工类私有继承people类int m_num;/工号public:char department10;/部门member(long n,char*na,char s=m,int mn=0,char*md=0):people(n,na,s)m_num=mn;strcpy(department,md);/构造函数void m_show()cout教工t;p_show();/访问基类的公有成员cout教工编号:m_num=m_num单位=departmentendl;class worker:public member/工人类公有继承类
9、memberchar station10;/岗位public:worker(long n,char*na,char s=m,int mn=0,char*md=0,char*st=0):member(n,na,s,mn,md)strcpy(station,st);/构造函数void w_show()cout工人t;m_show();/访问基类的公有成员cout岗位=stationendlendl;class teacher:private member/教师类私有继承基类memberchar course10;/执教课程public:teacher(long n,char*na,char s=m
10、,int mn=0,char*md=0,char*tc=0):member(n,na,s,mn,md)strcpy(course,tc);/构造函数void t_show()cout教师t;m_show();/访问基类的公有成员cout课程=courseendlendl;void main()worker w(123456,王祥,m,3761,生物系,实验室);w.w_show();w.m_show();/worker类公有继承member,所以可以直接访问member类的公有成员/w.p_show();member类私有继承people,不可以直接访问people类的公有成员teacher
11、t(661001,李辉,m,1954,计算机系,C+);t.t_show();/t.m_show();teacher类私有继承member,不可以直接访问member类的公有成员/t.p_show();teacher类私有继承member,member私有继承people类,不可以直接访问people类的公有成员执行结果为:工人教工人员:编号=123456姓名=王祥性别=m教工编号:m_num=3761单位=生物系岗位=实验室教工人员:编号=123456姓名=王祥性别=m教工编号:m_num=3761单位=生物系教师教工人员:编号=661001姓名=李辉性别=m教工编号:m_num=1954单
12、位=计算机系课程=C+3保护继承【例79-3】当派生类的继承方式是保护继承(protected)时,基类的public成员和protected成员被继承到派生类中成为派生类的protected成员,基类的private成员被继承到派生类中仍为private成员。【例7.4】类的保护继承。#includeclass Aint i;protected:int j;void show_A1()coutA保护显示:i=i j=jendl;public:A(int x,int y)i=x;j=y;void show_A2()coutA2在执行show_A1().;show_A1();coutA2执行完毕
13、。endl;class B:protected Aint x;public:B(int i,int j,int k):A(i,j)x=k;void show_B()coutB在执行show_A1().;show_A1();/保护继承可以访问A的保护成员coutB公有显示:x=xendl;coutB执行完毕。endl;class C:public Bpublic:C(int i,int j,int x):B(i,j,x)/空语句void show_C()coutC在执行show_A2().;show_A2();/说明可以访问A2,A2是B的保护成员coutC在执行show_A1().;/这两句是
14、多余的。show_A1();/说明可以访问A1,A1也是B的保护成员coutC在执行show_B().;show_B();coutC执行完毕。endl;void main()B b(1,2,3);b.show_B();/b.show_A2();B从A类保护继承,所以不能直接访问A类的公有成员C c(100,200,300);c.show_C();/c.show_A2();C从B类公有继承,而B从A保护继承,所以不能直接访问A类的公有成员执行结果为:B在执行show_A1().A保护显示:i=1 j=2B公有显示:x=3B执行完毕。C在执行show_A2().A2在执行show_A1().A保护
15、显示:i=100 j=200A2执行完毕。C在执行show_A1().A保护显示:i=100 j=200C在执行show_B().B在执行show_A1().A保护显示:i=100 j=200B公有显示:x=300B执行完毕。C执行完毕。ijxShow_A1()Show_A2()Show_B()在A 中私有保护无保护公有无在B中不可见保护私有保护保护公有在C中不可见保护不可见保护保护公有继承方式与成员的访问属性派生类的构造函数和析构函数在派生关系中,构造函数和析构函数是不能继承的,对派生类要重新定义构造函数和析构函数1、派生类构造函数的定义格式:派生类名(总参数列表):基类名(参数列表1),子
16、对象名1(参数列表2),子对象名2(参数列表3),派生类中新增数据成员的初始化语句 注意:1)派生类构造函数可在类中声明,类外定义,声明时不给出基类构造函数名及其参数列表;2)派生类构造函数定义时,其参数列表既有参数类型也有参数名称,而其后的基类的参数列表只有参数名称;执行构造函数的顺序是:派生类构造函数先调用基类的构造函数,对基类数据成员初始化,再执行派生类构造函数本身,对派生类数据成员初始化。包含子对象的派生类构造函数的执行顺序是:派生类构造函数先调用基类的构造函数,对基类数据成员初始化;再调用子对象构造函数,对子对象数据成员初始化,最后执行派生类构造函数本身,对派生类数据成员初始化。2派
17、生类的析构函数派生类析构函数没有函数类型、没有参数,其定义及使用方法与一般类的析构函数相同。派生类的析构函数用来对派生类中所增加的成员进行清理工作,同时系统会自动调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。析构函数的调用顺序与构造函数正好相反:先执行派生类的析构函数,然后调用子对象的析构函数,最后调用基类的析构函数,对基类进行清理。【例79-4】【例79-5】【例7.1】圆Circle类继承点Point类。class Point float x,y;public:Point(float a=0,float b=0)x=a;y=b;void SetP(float a=0,flo
18、at b=0)x=a;y=b;void Display()cout位置是:(x,y)n;class Circle:public Pointfloat r;public:Circle(float z=1,float x=0,float y=0):point(x,y)r=z;void SetC(float z=1,float x=0,float y=0)r=z;SetP(x,y);void Print()cout圆的;Display();cout圆的半径是:rendl;void main()Circle a(3.2);a.Print();a.SetC(6,8,2);a.Print();运行结果为:
19、圆的位置是:(0,0)圆的半径是:3.2圆的位置是:(8,2)圆的半径是:6【例7.5】声明一个派生类对象的实际操作步骤。设计基类。如要建立教工类,首先建立人员基类。class peoplechar name10,sex;/姓名,性别long idnumber;/身份号码public:people(long num=0,char*n=,char s=m)/构造函数idnumber=num;strcpy(name,n);sex=s;void p_show()cout人员:身份号=idnumber;cout姓名=name性别=sexendl;设计派生类。class member:public pe
20、ople/教工类公有继承people类int m_num;/工号public:char department10;/部门member(long n,char*na,char s=m,int mn=0,char*md=0):people(n,na,s)m_num=mn;strcpy(department,md);/构造函数void m_show()cout教工t;p_show();/访问基类的公有成员cout教工编号:m_num=m_num单位=departmentendl;定义对象。声明派生类member类对象。member w(123456,王一,m,789,计算机系);创建该类对象时,自动
21、调用member类的构造函数,再由member类的构造函数调用基类people类的构造函数。首先执行的是基类 people类的构造函数,创建它的成员,然后执行派生类member类的构造函数,从而创建它的成员。【例7.6】设计表示学校教师、职工和学生的类及其继承关系。#include#includeclass peoplechar name10,sex;/姓名,性别long idnumber;/身份号码public:people(long num=0,char*n=,char s=m)/构造函数 idnumber=num;strcpy(name,n);sex=s;void p_show()cou
22、t人员:身份号=idnumber;cout姓名=name性别=;if(sex=m|sex=M)cout男endl;if(sex=w|sex=W)cout女endl;class student:public people/学生类公有继承people类int s_num;/学号public:int s_class;/班级student(long n,char*na,char s=m,int sn=0,int sc=0):people(n,na,s)s_num=sn;s_class=sc;/构造函数void s_show()cout学生t;p_show();cout学号=s_num班级=s_clas
23、sendl;class member:public people/教工类公有继承people类int m_num;/工号public:char department10;/部门member(long n,char*na,char s=m,int mn=0,char*md=0):people(n,na,s)m_num=mn;strcpy(department,md);/构造函数void m_show()cout教工t;p_show();/访问基类的公有成员cout教工编号=m_num单位=department;class worker:public member/工人类公有继承类memberch
24、ar station10;/岗位public:worker(long n,char*na,char s=m,int mn=0,char*md=0,char*st=0):member(n,na,s,mn,md)strcpy(station,st);/构造函数void w_show()cout工人t;m_show();/访问基类的公有成员coutt岗位=stationendl;class teacher:public member/教师类公有继承基类memberchar course10;/执教课程public:teacher(long n,char*na,char s=m,int mn=0,ch
25、ar*md=0,char*tc=0):member(n,na,s,mn,md)strcpy(course,tc);/构造函数void t_show()cout教师t;m_show();/访问基类的公有成员coutt执教课程=courseendl;void main()people p(981102,赵一,w);p.p_show();student s(781010,钱二,m,1001,982);s.s_show();worker w(123456,孙三,m,123,计算机系,秘书);w.w_show();teacher t(661001,李四,m,456,计算机系,C+);t.t_show()
26、;cout直接访问公有基类的公有成员:endl;t.m_show();/公有继承的派生类对象直接访问基类的公有成员t.p_show();/公有继承的派生类对象直接访问基类的基类的公有成员coutt.departmentendl;/直接访问基类的公有数据成员 执行结果为:人员:身份号=981102姓名=赵一性别=女学生人员:身份号=781010姓名=钱二性别=男学号=1001班级=982工人教工人员:身份号=123456姓名=孙三性别=男教工编号=123单位=计算机系岗位=秘书教师教工人员:身份号=661001姓名=李四性别=男教工编号=456单位=计算机系执教课程=C+直接访问公有基类的公有成
27、员:教工人员:身份号=661001姓名=李四性别=男教工编号=456单位=计算机系人员:身份号=661001姓名=李四性别=男计算机系多重继承多重继承的声明class 派生类名:继承方式1 基类名1,继承方式2 基类名2,派生类新增加的成员;;例如:class D:public A,private B,protected C ;多重继承派生类的构造函数派生类名(总参数列表):基类名1(参数列表),基类名2(参数列表),子对象名1(参数列表),子对象名2(参数列表),派生类新增成员初始化语句;;多重继承构造函数的执行顺序与单继承相同,即先调用所有基类的构造函数,再调用子对象的构造函数,最后执行派
28、生类构造函数。【例79-6】【例7.7】一个简单的多继承。#includeclass Aint i;public:A(int ii=0)i=ii;void show()coutAshow()A中i=iendl;class Bint i;public:B(int ii=0)i=ii;void show()coutBshow()B中i=iendl;class C:public A,public Bint i;public:C(int iA=0,int iB=0,int iC=0):A(iA),B(iB)i=iC;void show()coutCshow()C中i=iendl;void main()
29、C c(1,2,3);c.Ashow();/调用对象c的基类A的成员函数show()c.Bshow();/调用对象c的基类B的成员函数show()c.show();/调用对象c所属的类C的成员函数show()执行结果为:Ashow()A中i=1Bshow()B中i=2Cshow()C中i=3【例7.8】西红柿的多继承。定义水果和蔬菜2个类作为基类,西红柿作为派生类。class fruit/定义水果类public:print()cout直接食用,味道鲜美!endl;class vegetable/定义蔬菜类public:print()cout烧炒烹炸,餐桌佳肴!endl;class tomato
30、:public fruit,public vegetable/定义西红柿类public:print()cout西红柿:酸甜可口!endl;void main()tomato t;t.print();t.fruitprint();/访问fruit基类的成员函数t.vegetableprint();/访问vegetable基类的成员函数运行结果为:西红柿:酸甜可口!直接食用,味道鲜美!烧炒烹炸,餐桌佳肴!二义性问题当一个派生类继承的多个基类中有同名成员时,可能出现对基类中某成员的访问不唯一的情况,这就是对基类成员访问的二义性问题。解决二义性问题的方法:1、在引用同名成员时,通过在成员名前加上类名和
31、作用域运算符“:”可以区别来自不同基类的成员。2、如果派生类中定义了与基类同名的成员,则派生类新增加的同名成员将覆盖基类中的同名成员。【例79-7】虚基类当一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则派生类中会保留这个共同基类成员的多份同名成员。C+引入了虚基类方法,使得派生类在继承间接共同基类时只保留一份同名成员。虚基类的声明虚基类的声明class 派生类名:virtual 继承方式 基类名例如:class A public:void display();protected:int a;class B:virtual public A protected:int b;cla
32、ss C:virtual public A protected:int c;class D:public B,public C public:void display_d();private:int d;虚基类的构造函数虚基类的初始化与一般的多重继承的初始化在语法上一致,但构造函数的执行次序不同:通常先执行虚基类的构造函数,再执行非虚基类的构造函数;当包含多个虚基类时,需按它们说明的顺序执行。【例79-8】【例7.9】一个虚基类继承的例子。#includeclass Apublic:void fn()coutA:fn()endl;class B1:virtual public A/虚拟继承pu
33、blic:void fn()coutB1:fn()endl;class B2:virtual public A/虚拟继承public:void fn()coutB2:fn()endl;class C1:public B1;class C2:public B2;class D:public C1,public C2;void main()D obj;obj.C1fn();obj.C2fn();obj.Afn();/可以执行,无二义性执行结果为:B1:fn1()B2:fn1()A:fn()若类A不是虚基类,则语句obj.Afn()就不能执行,这是因为计算机无法确定是执行B1继承的基类A的函数,还是
34、执行B2继承的基类A的函数,具有二义性【例7.10】虚基类的构造函数。#include#include class basechar name15;public:base(char*m=王五)strcpy(name,m);void show()coutbase输出:nameendl;class base1:virtual public basepublic:base1(char*m):base(m);class base2:virtual public basepublic:base2(char*m):base(m);class derive:virtual public base1,publ
35、ic base2char name15;public:derive(char*,char*,char*,char*);derive(char*,char*,char*);void showD()coutderive输出:nameendl;derivederive(char*p,char*q,char*r,char*t):base(p),base1(q),base2(r)strcpy(name,t);derivederive(char*p,char*q,char*r):base1(p),base2(q)strcpy(name,r);void main()derive d(赵易,钱耳,孙伞,李思)
36、;d.show();d.showD();derive c(赵易,钱耳,孙伞);c.show();c.showD();base1 b(周武);b.show();输出结果为:base输出:赵易derive输出:李思base输出:王五derive输出:孙伞base输出:周武【例7.11】设计一个表示在职学生的类。先设计一个基类people,表示一般人员的基本信息,再设计一个表示工作人员的类job,还要设计一个表示学生的类student,以这些类作为基类派生出在职学生类。#include#includeclass peoplechar name10,sex;/姓名,性别long idnumber;/身
37、份号码public:people(long num=0,char*n=,char s=m)/构造函数idnumber=num;strcpy(name,n);sex=s;void p_show()cout人员:身份号=idnumber;cout姓名=name性别=;if(sex=m|sex=M)cout男endl;if(sex=w|sex=W)cout女endl;class job:virtual public people/工作人员类公有继承people虚基类int m_num;/工号char department10;/单位public:job(long n,char*na,char s=m
38、,int mn=0,char*md=0):people(n,na,s)m_num=mn;strcpy(department,md);/构造函数void m_show()cout工作人员;cout编号=m_num单位=department;class student:virtual public people/学生类公有继承people虚基类int s_num;/学号int s_class;/班级public:student(long n,char*na,char s=m,int sn=0,int sc=0):people(n,na,s)s_num=sn;s_class=sc;/构造函数void
39、 s_show()cout在校学生;cout学号=s_num班级=s_classendl;class job_student:public job,public studentpublic:job_student(long n,char*na,char s=m,int mn=0,char*md=0,int No=0,int sta=1):job(n,na,s,mn,md),student(n,na,s,No,sta),people(n,na,s)/构造函数void t_show()cout在职学生endl;void main()job_student w(123456,赵一,m,123,商场,
40、456,2002);w.t_show();w.p_show();w.s_show();w.m_show();coutendl;输出结果为:在职学生人员:身份号=123456姓名=赵一性别=男在校学生学号=456班级=2002工作人员编号=123单位=商场【例7.12】给出下面程序的运行结果。#include class basescoreint math;protected:int eng;public:int chem;class dbase1:public basescorepublic:void input()couteng;coutchem;void output()cout 英语成绩
41、:engendl;cout C+成绩:chemendl;class dbase2:private basescorepublic:void input()couteng;coutchem;void output()cout 英语成绩:engendl;cout C+成绩:chemendl;void main()dbase1 pub;pub.input();dbase2 pri;pri.input();int s=pub.chem;coutsendl;pub.output();pri.output();输出结果为:输入英语成绩:82输入C+成绩:87输入英语成绩:91输入C+成绩:9587英语成绩:82C+成绩:87英语成绩:91C+成绩:95此课件下载可自行编辑修改,仅供参考!此课件下载可自行编辑修改,仅供参考!感谢您的支持,我们努力做得更好!谢谢感谢您的支持,我们努力做得更好!谢谢