计算机软件及应用继承doc资料_第1页
计算机软件及应用继承doc资料_第2页
计算机软件及应用继承doc资料_第3页
计算机软件及应用继承doc资料_第4页
计算机软件及应用继承doc资料_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算机软件及应用继承如果一个派生类只从一个基类派生,称为单继承;如果一个派生类从多个基类派生,称为多重继承关于继承的几点说明:①如果子类继承了父类,则子类自动具有父类的全部数据成员(数据结构)和成员函数(功能);但是,子类对父类成员的访问有所限制。②子类可以定义自己的成员是数据成员和成员函数。③基类、派生类或父类、子类都是“相对”的。一个类派生出新的类就是基类。派生类也可以被其他类继承,这个派生类同时也是基类。派生类的定义语法格式如下:class派生类名:[继承方式]基类名{新增私有成员声明语句列表public:新增公有成员声明语句列表protected:新增保护成员声明语句列表};例如:classBook //定义基类Book{private: intnum; //书号 floatprice; //定价 intsellnum; //销售量public: floatsale() //计算销售额 {returnprice*sellnum;}};classBook1:publicBook//定义派生类Book1{private: chartype; //定义图书类别,新增加的数据成员 charname[40];//书名,新增加的数据成员 charpublisher[20];//出版社,新增加的数据成员public: voidshow() //显示图书信息,新增加的成员函数 {cout<<"type:"<<type<<endl; cout<<"name:"<<name<<endl; cout<<"publisher:"<<publisher<<endl; }};派生类的构成派生类中的成员包括两部分,一部分是从基类继承过来的成员,一部分是在声明派生类时新增加的成员,每一部分均包括数据成员和成员函数。派生类要继承基类的所有成员,对基类的继承方式不同,其访问属性也不同派生类可以在原有基类成员的基础上添加新的成员,也可以更改原有成员属性。若在派生类中声明一个与基类成员同名的新成员,该成员就会覆盖原有的成员;若声明的是同名函数,要保证函数的参数也完全相同【回顾】类中的成员的不同访问权限public公有成员:一个类的公有成员允许本类的成员函数、本类的对象、公有派生类的成员函数、公有派生类的对象访问。private私有成员:一个类的私有成员只允许本类的成员函数访问。protected保护成员:具有私有成员和公有成员的特性,对其派生类而言是公有成员,对其他而言是私有成员。基类数据成员声明为保护的是有益的,派生类可以自由访问,外部不能访问,既实现了信息重用,又做到了信息隐藏。【例7.2】类的各种成员的访问权限。#include<iostream.h>classA{inti;//私有成员protected://保护成员intj;voidfn1(){cout<<″保护成员i=″<<i<<″j=″<<j<<endl;}public://公有成员A(intx,inty){i=x;j=y;}voidfn2()//成员函数可以访问保护成员{cout<<″公有成员i=″<<i<<″j=″<<j<<endl;fn1();}};voidmain(){Ax(21,63);x.fn2();}执行结果:公有成员i=21j=63保护成员i=21j=63在主程序中只能访问公有成员,成员函数可以访问保护成员和私有成员,在例7.2中,只能由函数fn2()访问函数fn1(),不能在主程序中调用x.fn1()。派生类的继承方式继承方式决定了子类对父类的访问权限,有3种继承方式:private、public和protected,默认为private1.公有继承【例79-1】当派生类的继承方式是公有继承(public)时,基类的public成员和protected成员的访问属性在派生类中保持不变,基类的private成员被继承到派生类中仍是基类的private成员。2.私有继承【例79-2】当派生类的继承方式是私有继承(private)时,基类的public成员和protected成员被继承到派生类中成为private成员,基类的private成员被继承到派生类中仍为private成员【例7.3】学校职工类的公有继承和私有继承。类people是基类,定义人的姓名、性别、身份号和对这3种数据的显示。类member私有继承people,定义了职工号、部门和信息显示,类member生成的对象不能直接访问类people中的任何成员。类worker公有继承类member,定义了岗位和信息显示,类worker生成的对象可以直接访问类member中的公有成员。类teacher私有继承类member,定义了执教课程和信息显示,类teacher生成的对象不能直接访问类member中的任何成员。#include<iostream.h>#include<string.h>classpeople{charname[10],sex;//姓名,性别longidnumber;//身份号码public:people(longnum=0,char*n=″″,chars=′m′)//构造函数{idnumber=num;strcpy(name,n);sex=s;}voidp_show(){cout<<″人员:身份号=″<<idnumber;cout<<″姓名=″<<name<<″性别=″<<sex<<endl;}};classmember:privatepeople//教工类私有继承people类{intm_num;//工号public:chardepartment[10];//部门member(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″):people(n,na,s){m_num=mn;strcpy(department,md);}//构造函数voidm_show(){cout<<″教工\\t″;p_show();//访问基类的公有成员cout<<″教工编号:m_num=″<<m_num<<″单位=″<<department<<endl;}};classworker:publicmember//工人类公有继承类member{charstation[10];//岗位public:worker(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″,char*st=″\\0″):member(n,na,s,mn,md){strcpy(station,st);}//构造函数voidw_show(){cout<<″工人\\t″;m_show();//访问基类的公有成员cout<<″岗位=″<<station<<endl<<endl;}};classteacher:privatemember//教师类私有继承基类member{charcourse[10];//执教课程public:teacher(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″,char*tc=″\\0″):member(n,na,s,mn,md){strcpy(course,tc);}//构造函数voidt_show(){cout<<″教师\\t″;m_show();//访问基类的公有成员cout<<″课程=″<<course<<endl<<endl;}};voidmain(){workerw(123456,″王祥″,′m′,3761,″生物系″,″实验室″);w.w_show();w.m_show();//worker类公有继承member,所以可以直接访问member类的公有成员//w.p_show();member类私有继承people,不可以直接访问people类的公有成员teachert(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 单位=计算机系课程=C++3.保护继承【例79-3】当派生类的继承方式是保护继承(protected)时,基类的public成员和protected成员被继承到派生类中成为派生类的protected成员,基类的private成员被继承到派生类中仍为private成员。【例7.4】类的保护继承。#include<iostream.h>classA{inti;protected:intj;voidshow_A1(){cout<<″A保护显示:i=″<<i<<″j=″<<j<<endl;}public:A(intx,inty){i=x;j=y;}voidshow_A2(){cout<<″A2在执行show_A1()......″;show_A1();cout<<″A2执行完毕。″<<endl;}};classB:protectedA{intx;public:B(inti,intj,intk):A(i,j){x=k;}voidshow_B(){cout<<″B在执行show_A1()......″;show_A1();//保护继承可以访问A的保护成员cout<<″B公有显示:x=″<<x<<endl;cout<<″B执行完毕。″<<endl;}};classC:publicB{public:C(inti,intj,intx):B(i,j,x){}//空语句voidshow_C(){cout<<″C在执行show_A2()......″;show_A2();//说明可以访问A2,A2是B的保护成员cout<<″C在执行show_A1()......″;//这两句是多余的。show_A1();//说明可以访问A1,A1也是B的保护成员cout<<″C在执行show_B()......″;show_B();cout<<″C执行完毕。″<<endl;}};voidmain(){Bb(1,2,3);b.show_B();//b.show_A2();B从A类保护继承,所以不能直接访问A类的公有成员Cc(100,200,300);c.show_C();//c.show_A2();C从B类公有继承,而B从A保护继承,所以不能直接访问A类的公有成员}执行结果为:B在执行show_A1()......A保护显示:i=1j=2B公有显示:x=3B执行完毕。C在执行show_A2()......A2在执行show_A1()......A保护显示:i=100j=200A2执行完毕。C在执行show_A1()......A保护显示:i=100j=200C在执行show_B()......B在执行show_A1()......A保护显示:i=100j=200B公有显示:x=300B执行完毕。C执行完毕。ijxShow_A1()Show_A2()Show_B()在A中私有保护无保护公有无在B中不可见保护私有保护保护公有在C中不可见保护不可见保护保护公有继承方式与成员的访问属性派生类的构造函数和析构函数在派生关系中,构造函数和析构函数是不能继承的,对派生类要重新定义构造函数和析构函数1、派生类构造函数的定义格式:派生类名(总参数列表):基类名(参数列表1),子对象名1(参数列表2),子对象名2(参数列表3),…{派生类中新增数据成员的初始化语句}注意:1)派生类构造函数可在类中声明,类外定义,声明时不给出基类构造函数名及其参数列表;2)派生类构造函数定义时,其参数列表既有参数类型也有参数名称,而其后的基类的参数列表只有参数名称;执行构造函数的顺序是:派生类构造函数先调用基类的构造函数,对基类数据成员初始化,再执行派生类构造函数本身,对派生类数据成员初始化。包含子对象的派生类构造函数的执行顺序是:派生类构造函数先调用基类的构造函数,对基类数据成员初始化;再调用子对象构造函数,对子对象数据成员初始化,最后执行派生类构造函数本身,对派生类数据成员初始化。2.派生类的析构函数派生类析构函数没有函数类型、没有参数,其定义及使用方法与一般类的析构函数相同。派生类的析构函数用来对派生类中所增加的成员进行清理工作,同时系统会自动调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。析构函数的调用顺序与构造函数正好相反:先执行派生类的析构函数,然后调用子对象的析构函数,最后调用基类的析构函数,对基类进行清理。【例79-4】【例79-5】【例7.1】圆Circle类继承点Point类。classPoint{floatx,y;public:Point(floata=0,floatb=0){x=a;y=b;}voidSetP(floata=0,floatb=0){x=a;y=b;}voidDisplay(){cout<<″位置是:(″<<x<<′,′<<y<<″)\\n″;}};classCircle:publicPoint{floatr;public:Circle(floatz=1,floatx=0,floaty=0):point(x,y){r=z;}voidSetC(floatz=1,floatx=0,floaty=0){r=z;SetP(x,y);}voidPrint(){cout<<″圆的″;Display();cout<<″圆的半径是:″<<r<<endl;}};voidmain(){Circlea(3.2);a.Print();a.SetC(6,8,2);a.Print();}运行结果为:圆的位置是:(0,0)圆的半径是:3.2圆的位置是:(8,2)圆的半径是:6【例7.5】声明一个派生类对象的实际操作步骤。①设计基类。如要建立教工类,首先建立人员基类。classpeople{charname[10],sex;//姓名,性别longidnumber;//身份号码public:people(longnum=0,char*n=″″,chars=′m′)//构造函数{idnumber=num;strcpy(name,n);sex=s;}voidp_show(){cout<<″人员:身份号=″<<idnumber;cout<<″姓名=″<<name<<″性别=″<<sex<<endl;}};②设计派生类。classmember:publicpeople//教工类公有继承people类{intm_num;//工号public:chardepartment[10];//部门member(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″):people(n,na,s){m_num=mn;strcpy(department,md);}//构造函数voidm_show(){cout<<″教工\\t″;p_show();//访问基类的公有成员cout<<″教工编号:m_num=″<<m_num<<″单位=″<<department<<endl;}};③定义对象。声明派生类member类对象。memberw(123456,″王一″,′m′,789,″计算机系″);创建该类对象时,自动调用member类的构造函数,再由member类的构造函数调用基类people类的构造函数。首先执行的是基类people类的构造函数,创建它的成员,然后执行派生类member类的构造函数,从而创建它的成员。【例7.6】设计表示学校教师、职工和学生的类及其继承关系。#include<iostream.h>#include<string.h>classpeople{charname[10],sex;//姓名,性别longidnumber;//身份号码public:people(longnum=0,char*n=″″,chars=′m′)//构造函数{idnumber=num;strcpy(name,n);sex=s;}voidp_show(){cout<<″人员:身份号=″<<idnumber;cout<<″姓名=″<<name<<″性别=″;if(sex==′m′||sex==′M′)cout<<″男″<<endl;if(sex==′w′||sex==′W′)cout<<″女″<<endl;}};classstudent:publicpeople//学生类公有继承people类{ints_num;//学号public:ints_class;//班级student(longn,char*na,chars=′m′,intsn=0,intsc=0):people(n,na,s){s_num=sn;s_class=sc;}//构造函数voids_show(){cout<<″学生\\t″;p_show();cout<<″学号=″<<s_num<<″班级=″<<s_class<<endl;}};classmember:publicpeople//教工类公有继承people类{intm_num;//工号public:chardepartment[10];//部门member(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″):people(n,na,s){m_num=mn;strcpy(department,md);}//构造函数voidm_show(){cout<<″教工\\t″;p_show();//访问基类的公有成员cout<<″教工编号=″<<m_num<<″单位=″<<department;}};classworker:publicmember//工人类公有继承类member{charstation[10];//岗位public:worker(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″,char*st=″\\0″):member(n,na,s,mn,md){strcpy(station,st);}//构造函数voidw_show(){cout<<″工人\\t″;m_show();//访问基类的公有成员cout<<″\\t岗位=″<<station<<endl;}};classteacher:publicmember//教师类公有继承基类member{charcourse[10];//执教课程public:teacher(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″,char*tc=″\\0″):member(n,na,s,mn,md){strcpy(course,tc);}//构造函数voidt_show(){cout<<″教师\\t″;m_show();//访问基类的公有成员cout<<″\\t执教课程=″<<course<<endl;}};voidmain(){peoplep(981102,″赵一″,′w′);p.p_show();students(781010,″钱二″,′m′,1001,982);s.s_show();workerw(123456,″孙三″,′m′,123,″计算机系″,″秘书″);w.w_show();teachert(661001,″李四″,′m′,456,″计算机系″,″C++″);t.t_show();cout<<″直接访问公有基类的公有成员:″<<endl;t.m_show();//公有继承的派生类对象直接访问基类的公有成员t.p_show();//公有继承的派生类对象直接访问基类的基类的公有成员cout<<t.department<<endl;//直接访问基类的公有数据成员}执行结果为:人员:身份号=981102 姓名=赵一 性别=女学生 人员:身份号=781010 姓名=钱二 性别=男学号=1001 班级=982工人 教工 人员:身份号=123456 姓名=孙三 性别=男教工编号=123 单位=计算机系 岗位=秘书教师 教工 人员:身份号=661001 姓名=李四 性别=男教工编号=456 单位=计算机系 执教课程=C++直接访问公有基类的公有成员:教工 人员:身份号=661001 姓名=李四 性别=男教工编号=456 单位=计算机系人员:身份号=661001 姓名=李四 性别=男计算机系多重继承多重继承的声明class派生类名:继承方式1基类名1,继承方式2基类名2,…{派生类新增加的成员;};例如:classD:publicA,privateB,protectedC{…};多重继承派生类的构造函数派生类名(总参数列表):基类名1(参数列表),基类名2(参数列表),…,子对象名1(参数列表),子对象名2(参数列表),…{派生类新增成员初始化语句;};多重继承构造函数的执行顺序与单继承相同,即先调用所有基类的构造函数,再调用子对象的构造函数,最后执行派生类构造函数。【例79-6】【例7.7】一个简单的多继承。#include<iostream.h>classA{inti;public:A(intii=0){i=ii;}voidshow(){cout<<″A∷show()A中i=″<<i<<endl;}};classB{inti;public:B(intii=0){i=ii;}voidshow(){cout<<″B∷show()B中i=″<<i<<endl;}};classC:publicA,publicB{inti;public:C(intiA=0,intiB=0,intiC=0):A(iA),B(iB){i=iC;}voidshow(){cout<<″C∷show()C中i=″<<i<<endl;}};voidmain(){Cc(1,2,3);c.A∷show();//调用对象c的基类A的成员函数show()c.B∷show();//调用对象c的基类B的成员函数show()c.show();//调用对象c所属的类C的成员函数show()}执行结果为:A∷show()A中i=1B∷show()B中i=2C∷show()C中i=3【例7.8】西红柿的多继承。定义水果和蔬菜2个类作为基类,西红柿作为派生类。classfruit{//定义水果类public:print(){cout<<″直接食用,味道鲜美!″<<endl;}};classvegetable{//定义蔬菜类public:print(){cout<<″烧炒烹炸,餐桌佳肴!″<<endl;}};classtomato:publicfruit,publicvegetable{//定义西红柿类public:print(){cout<<″西红柿:酸甜可口!″<<endl;}};voidmain(){tomatot;t.print();t.fruit∷print();//访问fruit基类的成员函数t.vegetable∷print();//访问vegetable基类的成员函数}运行结果为:西红柿:酸甜可口!直接食用,味道鲜美!烧炒烹炸,餐桌佳肴!二义性问题当一个派生类继承的多个基类中有同名成员时,可能出现对基类中某成员的访问不唯一的情况,这就是对基类成员访问的二义性问题。解决二义性问题的方法:1、在引用同名成员时,通过在成员名前加上类名和作用域运算符“::”可以区别来自不同基类的成员。2、如果派生类中定义了与基类同名的成员,则派生类新增加的同名成员将覆盖基类中的同名成员。【例79-7】虚基类当一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则派生类中会保留这个共同基类成员的多份同名成员。C++引入了虚基类方法,使得派生类在继承间接共同基类时只保留一份同名成员。虚基类的声明虚基类的声明class派生类名:virtual继承方式基类名例如:classA{public: voiddisplay();protected: inta;};classB:virtualpublicA{protected: intb;};classC:virtualpublicA{protected:intc;};classD:publicB,publicC{public:voiddisplay_d();private:intd;};虚基类的构造函数虚基类的初始化与一般的多重继承的初始化在语法上一致,但构造函数的执行次序不同:通常先执行虚基类的构造函数,再执行非虚基类的构造函数;当包含多个虚基类时,需按它们说明的顺序执行。【例79-8】【例7.9】一个虚基类继承的例子。#include<iostream.h>classA{public:voidfn(){cout<<″A:fn()″<<endl;}};classB1:virtualpublicA{//虚拟继承public:voidfn(){cout<<″B1:fn()″<<endl;}};classB2:virtualpublicA{//虚拟继承public:voidfn(){cout<<″B2:fn()″<<endl;}};classC1:publicB1{};classC2:publicB2{};classD:publicC1,publicC2{};voidmain(){Dobj;obj.C1∷fn();obj.C2∷fn();obj.A∷fn();//可以执行,无二义性}执行结果为:B1:fn1()B2:fn1()A:fn()若类A不是虚基类,则语句obj.A∷fn()就不能执行,这是因为计算机无法确定是执行B1继承的基类A的函数,还是执行B2继承的基类A的函数,具有二义性【例7.10】虚基类的构造函数。#include<iostream.h>#include<string.h>classbase{charname[15];public:base(char*m=″王五″){strcpy(name,m);}voidshow(){cout<<″base输出:″<<name<<endl;}};classbase1:virtualpublicbase{public:base1(char*m):base(m){}};classbase2:virtualpublicbase{public:base2(char*m):base(m){}};classderive:virtualpublicbase1,publicbase2{charname[15];public:derive(char*,char*,char*,char*);derive(char*,char*,char*);voidshowD(){cout<<″derive输出:″<<name<<endl;}};derive∷derive(char*p,char*q,char*r,char*t):base(p),base1(q),base2(r){strcpy(name,t);}derive∷derive(char*p,char*q,char*r):base1(p),base2(q){strcpy(name,r);}voidmain(){derived(″赵易″,″钱耳″,″孙伞″,″李思″);d.show();d.showD();derivec(″赵易″,″钱耳″,″孙伞″);c.show();c.showD();base1b(″周武″);b.show();}输出结果为:base输出:赵易derive输出:李思base输出:王五derive输出:孙伞base输出:周武【例7.11】设计一个表示在职学生的类。先设计一个基类people,表示一般人员的基本信息,再设计一个表示工作人员的类job,还要设计一个表示学生的类student,以这些类作为基类派生出在职学生类。#include<iostream.h>#include<string.h>classpeople{charname[10],sex;//姓名,性别longidnumber;//身份号码public:people(longnum=0,char*n=″″,chars=′m′)//构造函数{idnumber=num;strcpy(name,n);sex=s;}voidp_show(){cout<<″人员:身份号=″<<idnumber;cout<<″姓名=″<<name<<″性别=″;if(sex==′m′||sex==′M′)cout<<″男″<<endl;if(sex==′w′||sex==′W′)cout<<″女″<<endl;}};classjob:virtualpublicpeople//工作人员类公有继承people虚基类{intm_num;//工号chardepartment[10];//单位public:job(longn,char*na,chars=′m′,intmn=0,char*md=″\\0″):people(n,na,s){m_num=mn;strcpy(department,md);}//构造函数voidm_show(){cout<<″工作人员″;cout<<″编号=″<<m_num<<″单位=″

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论