《继承与派生》PPT课件.ppt
第第5章章继承和派生1本章内容本章内容p5.1 继承和派生的概念p5.2 派生类的声明方法p5.3 派生类的构成p5.4 派生类成员的访问属性p5.5 派生类的构造函数和析构函数p5.6 多重继承p5.7 基类和派生类的转换p5.8 继承与组合2目标目标l理解派生和继承的相关概念;l掌握派生类的声明方式l掌握派生类的构成和成员的访问属性;l掌握派生类构造函数和析构函数的使用方法;l掌握多重继承的方法;l理解基类和派生类的转换方法;l理解继承与组合的含义。35.1 继承与派生的概念继承与派生的概念继承:继承是类之间定义的一种重要关系。人人学生学生老师老师大学生大学生研究生研究生硕士生硕士生博士生博士生专科生专科生本科生本科生在职研究生在职研究生45.1 继承与派生的概念继承与派生的概念B类继承A类,或称从类A派生出B类,则A类称为基类(父类),类B称为派生类(子类)。人人学生学生老师老师大学生大学生研究生研究生硕士生硕士生博士生博士生专科生专科生本科生本科生在职研究生在职研究生55.1 继承与派生的概念继承与派生的概念单继承:派生类从一个基类派生的继承关系。多继承:派生类从多个基类派生的继承关系。人人学生学生老师老师大学生大学生研究生研究生硕士生硕士生博士生博士生专科生专科生本科生本科生在职研究生在职研究生65.1 继承与派生的概念继承与派生的概念l例:l1、定义一个学生类Student,包括学生和姓名,以及显示信息的函数。l2、定义一个大学生类CollegeStudent,包括学生、姓名和专业,以及显示信息的函数。75.1 继承与派生的概念继承与派生的概念class Student public:void display()coutnum;coutname;private:int num;string name;class CollegeStudent public:void display()coutnum;coutname;coutspeciality;private:int num;string name;string speciality;能否在定义能否在定义CollegeStudent时利用时利用Student,而不用重新而不用重新定义已有的成员?定义已有的成员?85.2 派生类的声明方式派生类的声明方式l声明派生类的一般形式为:class 派生类名:继承方式 基类名 派生类新增成员;l继承方式:public、private和protected,默认为private。95.2 派生类的声明方式派生类的声明方式class CollegeStudent:public Student public:void display1()coutnumname;void display()coutnumname;private:int num;string name;class CollegeStudent:public Student public:void display()coutspeciality;private:string speciality;135.4 派生类成员的访问属性派生类成员的访问属性(一)公有继承public 成员protected 成员private 成员public 成员protected 成员private 成员基类基类派生类派生类不可访问14class Student public:void display()coutnumname;private:int num;string name;class CollegeStudent:public Student public:void display1()coutnumname speciality;private:string speciality;num和和name在派在派生类中不可访问。生类中不可访问。15class Student;class CollegeStudent:public Student public:void display1()coutspeciality;private:string speciality;void main()CollegeStudent s;s.display();s.display1();return 0;165.4 派生类成员的访问属性派生类成员的访问属性(二)私有继承public 成员protected 成员private 成员public 成员protected 成员private 成员基类基类派生类派生类不可访问private 成员private 成员17class Student public:void display()coutnumname;private:int num;string name;class CollegeStudent:private Student public:void display1()coutspeciality;private:string speciality;void main()CollegeStudent s;s.display();s.display1();s.speciality=“Computer”;return 0;18class Student public:void display()coutnumname;private:int num;string name;class CollegeStudent:private Student public:void display1()display();coutnumname;void display()coutnumspeciality;void display1()display();coutspeciality;private:string speciality;int main()CollegeStudent s;s.get_value1();s.display1();return 0;205.4 派生类成员的访问属性派生类成员的访问属性(三)保护继承public 成员protected 成员private 成员public 成员protected 成员private 成员基类基类派生类派生类不可访问protected 成员protected 成员215.4 派生类成员的访问属性派生类成员的访问属性(三)保护继承l由protected声明的成员称为受保护成员,简称保护成员。l在同一类中保护成员和私有成员一样,只能被类内部的成员函数访问,而不能被类外访问。l保护成员可以被派生类的成员函数访问。22class Student private:int num;protected:string name;class CollegeStudent:protected Student public:void display()coutnum;coutnumname;void getvalue()cinnum;/void display()coutnumendlnameendl;void display()coutnumnamespeciality;void display1()display();coutspecialityendlnameendl;private:string speciality;int main()CollegeStudent s;s.getvalue1();s.name=“dfsd343”;/error 类外无权访问类外无权访问/s.display();s.display1();return 0;24总结总结l类的成员的访问属性lPublic:可以在类内通过成员函数来访问,也可以在类外通过对象来访问。lPrivate:只能在类内通过成员函数来访问lProtected:只能在类内通过成员函数来访问25总结总结l派生后成员访问属性在派生类中的变化:l原来在基类中的访问属性与上继承时的继承方式,即为基类成员在派生类中新的访问属性。Class 基类基类 public:成员:成员j1 protected:成员:成员j2 private:成员:成员j3;Class 派生类:派生类:基类基类 public:成员:成员p1 protected:成员:成员p2 private:成员:成员p3;public,j1,j226总结总结l派生后成员访问属性在派生类中的变化:l原来在基类中的访问属性与上继承时的继承方式,即为基类成员在派生类中新的访问属性。Class 基类基类 public:成员:成员j1 protected:成员:成员j2 private:成员:成员j3;Class 派生类:派生类:基类基类 public:成员:成员p1 protected:成员:成员p2 private:成员:成员p3;Protected,j2,j127总结总结l派生后成员访问属性在派生类中的变化:l原来在基类中的访问属性与上继承时的继承方式,即为基类成员在派生类中新的访问属性。Class 基类基类 public:成员:成员j1 protected:成员:成员j2 private:成员:成员j3;Class 派生类:派生类:基类基类 public:成员:成员p1 protected:成员:成员p2 private:成员:成员p3;private,j2,j1P162 表表28练习:分析多级派生时访问属性练习:分析多级派生时访问属性class A /基类public:int i;protected:void f2();int j;private:int k;class B:public A /public方式public:void f3();protected:void f4();private:int m;class C:protected B /protected方式public:void f5();private:int n;常用继承方式常用继承方式public295.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(一)简单派生类的构造函数l简单派生类只有一个基类,数据成员中不包括基类的对象。l简单派生类构造函数的定义形式为:派生类构造函数(总参数列表):基类构造基类构造函数函数(参数列表参数列表)派生类中新增新增数据成员初始化;30class Stu public:Stu(int n,string na)num=n;name=na;protected:int num;string name;class ColStu:public Stu public:ColStu(int n,string na,string s):Stu(n,na)speciality=s;void display()coutnumnamespeciality;private:string speciality;315.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(一)简单派生类的构造函数l构造函数的执行顺序:1.基类的构造函数。2.派生类的构造函数。l析构函数的执行顺序:1.派生类的析构函数。2.基类的析构函数。32简单派生类的构造函数简单派生类的构造函数派生类构造函数(总参数列表):基类构造函数(参数列表)派生类中新增数据成员初始化;l构造函数的执行顺序:1.基类的构造函数。2.派生类的构造函数。l析构函数的执行顺序:1.派生类的析构函数。2.基类的析构函数。335.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(二)有子对象子对象的派生类的构造函数l有子对象的派生类是指类的成员包括类类的成员包括类的对象。的对象。class Stu protected:int num;string name;class ColStu:public Stu public:void display();private:string speciality;Stu s;345.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(二)有子对象的派生类的构造函数l有子对象的派生类构造函数的一般形式为:派生类构造函数(总参数列表):基类构造基类构造函数(参数列表)函数(参数列表),子对象名(参数列表)子对象名(参数列表)派生类中新增数据成员初始化;355.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(二)有子对象的派生类的构造函数l构造函数的执行顺序:1.基类的构造函数。2.子对象的构造函数。子对象的构造函数。3.派生类的构造函数。365.5 派生类的构造函数和析构函数派生类的构造函数和析构函数class B public:B(int bb)b=bb;private:int b;class C:public B public:C(int cc)c=cc;private:B memB;int c;找问题找问题 Cint b;/基类数据成员基类数据成员 int c;/新增数据成员新增数据成员 B menB;/内嵌内嵌子对象子对象 如何初如何初始化?始化?37class B private:int b;public:B(int bb)b=bb;coutB:bendl;class C:public B public:C(int aa,int bb,int cc):B(aa),memB(bb)c=cc;coutC:cendl;private:B memB;int c;int main()C c(1,2,3);385.5 派生类的构造函数和析构函数派生类的构造函数和析构函数(三)多层派生时的构造函数l一个类不仅可以派生出一个派生类,派生类还可以继续派生,形成派生的层次结构。l多层继承时的访问属性l多层派生时的构造函数不用列出每一层派生类的构造函数,只须只须写出其上一层派生类(即直接基类)的构造函数即可。39class Apublic:A(int aa)a=aa;A()()cout“”;private:int a;class B:public A public:B(int aa,int bb):A(aa)b=bb;private:int b;class C:public B public:C(int aa,int bb,int cc):B(aa,bb)c=cc;private:int c;40class Apublic:A(int aa)a=aa;void display()coutaendl;private:int a;class B:public A public:B(int aa,int bb):A(aa)b=bb;void display1()display();coutbendl;private:int b;class C:public B public:C(int aa,int bb,int cc):B(aa,bb)c=cc;void display2()display1();coutcendl;private:int c;int main()C c(1,2,3);c.display2();return 0;415.5 派生类的构造函数和析构函数派生类的构造函数和析构函数l什么时候在声明派生类的构造函数时需要对基类或对象成员进行初始化?l如果派生类的基类或内嵌子对象所属的类中没有提供默认构造函数时,派生类需要声明构造函数,对继承的基类成员和内嵌子对象的成员进行初始化。425.5 派生类的构造函数和析构函数派生类的构造函数和析构函数l构造函数的执行顺序:1.基类的构造函数。2.子对象的构造函数。3.派生类的构造函数。l析构函数的执行顺序:1.派生类的析构函数。2.子对象的析构函数。3.基类的析构函数。43class Apublic:A(int aa)a=aa;coutA:aendl;A()coutAendl;private:int a;class Bpublic:B(int bb)b=bb;coutB:bendl;B()coutBendl;private:int b;class C:public Bpublic:C(int aa,int bb,int cc):B(bb),a(aa)c=cc;coutC:cendl;C()coutCendl;private:A a;int c;void main()C c(1,2,3);44NO.2455.6 多重继承多重继承l多重继承:一个派生类同时继承多个基类。465.6 多重继承多重继承(一)声明多重继承的方法class 派生类名:继承方式基类名1,继承方式基类名2,.,继承方式基类名n 派生类成员声明;47class Apublic:displayA couta;int a;class B public:displayB coutb;int b;class C:public A,public B public:displayC coutc;private:int c;48Cint a;int b;int c;void DisplayA();void DisplayB();void DisplayC();Aint a;void DisplayA();Bint b;void DisplayB();5.6 多重继承多重继承495.6 多重继承多重继承(二)多重继承派生类的构造函数l多继承下的构造函数和析构函数与单继承下的构造函数和析构函数是相似的,派生类的构造函数需要对基类成员、内嵌子对象和新增成员进行初始化。50class A public:A(int aa=0)a=aa;private:int a;class B public:B(int bb=0)b=bb;private:int b;class C:public A,public B public:private:A a;B b;int c;构造函数构造函数C(int a1,int a2,int b1,int b2,int cc):A(a1),a(a2),B(b1),b(b2)c=cc;51class A public:A(int aa=0)a=aa;void display()coutaendl;private:int a;class B public:B(int bb=0)b=bb;void display()coutbendl;private:int b;class C:public A,public B public:C(int a1,int a2,int b1,int b2,int cc):A(a1),a(a2),B(b1),b(b2)c=cc;void display()coutcendl;private:A a;B b;int c;int main()C c(1,10,2,20,30);/c.A:display();/c.B:display();c.display();52class A public:A(int aa=0)a=aa;void display()coutaendl;private:int a;class B public:B(int bb=0)b=bb;void display()coutbendl;private:int b;class C:public A,public B public:C(int a1,int a2,int b1,int b2,int cc):A(a1),a(a2),B(b1),b(b2)c=cc;void display()a.display();b.display();coutcendl;private:A a;B b;int c;int main()C c(1,10,2,20,30);c.A:display();c.B:display();c.display();53class B1 public:B1(int i)coutB1 iendl;class B2 public:B2(int j)coutB2 jendl;class B3 public:B3()coutB3*endl;class C:public B2,public B1,public B3public:C(int a,int b,int c,int d):B1(a),memB2(d),memB1(c),B2(b)private:B1 memB1;B2 memB2;B3 memB3;void main()C obj(1,2,3,4);54l(二)多重继承派生类的构造函数l格式:派生类构造函数名(总参数列表):基类1构造函数(参数列表),基类2构造函数(参数列表),子对象 1(参数列表),子对象 2(参数列表)派生类中新增数据成员初始化语句l注意:调用基类、子对象的构造函数的顺序是按照声明派生类时基类、子对象出现的顺序来调用的。555.6 多重继承多重继承(三)多重继承引起的二义性问题class A public:void display()coutAendl;class B public:void display()coutBendl;class C:public A,public B;void main()C c;c.display();找问题找问题565.6 多重继承多重继承(三)多重继承引起的二义性问题Avoid display();Bvoid display();Cvoid A:display();void B:display();C c;c.display();C c;c.A:display();c.B:display();57class A public:void display()coutAendl;class B public:void display()coutBendl;class C:public A,public B public:void display()coutCendl;void main()C c;c.display();5.6 多重继承多重继承58复习复习l5.5 派生类的构造函数和析构函数l(一)简单派生类的构造函数l(二)有子对象的派生类的构造函数l(三)多层派生时的构造函数l5.6 多重继承l(一)声明多重继承的方法l(二)多重继承派生类的构造函数l(三)多重继承引起的二义性问题59简单派生类的构造函数简单派生类的构造函数派生类构造函数(总参数列表):基类构造函数(参数列表)派生类中新增数据成员初始化;l构造函数的执行顺序:1.基类的构造函数。2.派生类的构造函数。l析构函数的执行顺序:1.派生类的析构函数。2.基类的析构函数。60class Stu public:Stu(int n,string na)num=n;name=na;protected:int num;string name;class ColStu:public Stu public:ColStu(int n,string na,string s):Stu(n,na)speciality=s;void display()coutnumnamespeciality;private:string speciality;61(二)有子对象的派生类的构造函数(二)有子对象的派生类的构造函数派生类构造函数(总参数列表):基类构造函数(参数列表),子对象名(参数列表)派生类中新增数据成员初始化;l构造函数的执行顺序:1.基类的构造函数。2.子对象的构造函数。3.派生类的构造函数。62class B private:int b;public:B(int bb)b=bb;coutB:bendl;class C:public B public:C(int aa,int bb,int cc):B(aa),memB(bb)c=cc;coutC:cendl;private:B memB;int c;void main()C c(1,2,3);63(三)多层派生时的构造函数l多层派生时的构造函数不用列出每一层派生类的构造函数,只须写出其上一层派生类(即直接基类)的构造函数即可。64class Apublic:A(int aa)a=aa;private:int a;class B:public A public:B(int aa,int bb):A(aa)b=bb;private:int b;class C:public B public:C(int aa,int bb,int cc):B(aa,bb)c=cc;private:int c;655.6 多重继承多重继承(一)声明多重继承的方法class 派生类名:继承方式基类名1,继承方式基类名2,.,继承方式基类名n 派生类成员声明;66class Apublic:displayA couta;int a;class B public:displayB coutb;int b;class C:public A,public B public:displayC coutc;private:int c;67l(二)多重继承派生类的构造函数l格式:l派生类构造函数名(总参数列表):基类派生类构造函数名(总参数列表):基类1 1构构造函数(参数列表),基类造函数(参数列表),基类2 2构造函数(参数构造函数(参数列表),子对象列表),子对象 1 1(参数列表),子对象(参数列表),子对象 2 2(参数列表)(参数列表)l l派生类中新增数据成员初始化语句派生类中新增数据成员初始化语句l l注意:调用基类、子对象的构造函数的顺序是按照声明派生类时基类、子对象出现的顺序来调用的。68class B1 public:B1(int i)coutB1 iendl;class B2 public:B2(int j)coutB2 jendl;class B3 public:B3()coutB3*endl;class C:public B2,public B1,public B3public:C(int a,int b,int c,int d):B1(a),memB2(d),memB1(c),B2(b)private:B1 memB1;B2 memB2;B3 memB3;void main()C obj(1,2,3,4);695.6 多重继承多重继承l(三)多重继承引起的二义性问题l1、两个基类有同名成员l2、两个基类和派生类有同名成员l3、两个直接基类都继承于同一基类705.6 多重继承多重继承(三)多重继承引起的二义性问题Avoid display();Bvoid display();Cvoid A:display();void B:display();C c;c.display();C c;c.A:display();c.B:display();715.6 多重继承多重继承(三)多重继承引起的二义性问题l派生类新增加的同名成员将覆盖基类中的同名成员。72class A public:int a;void display()coutaendl;class B:public A ;class C:public A ;class D:public B,public C public:void display()coutaendl;void main()D d;d.display();/D类的类的display()c.B:display();/B类从类从A类继承的类继承的display()c.C:display();/C类从类从A类继承的类继承的display()73第二次课第二次课745.6 多重继承多重继承Aint a;void display();Eint B:a;int C:a;int D:a;void B:display();void C:display();void D:display();Bint A:a;void A:display();Dint A:a;void A:display();Cint A:a;void A:display();E中能否只保中能否只保留一份留一份A的的a和和display()?755.6 多重继承多重继承(四)虚基类l虚基类的作用:可以使得在继承间接共共同基类时只保留一份成员。同基类时只保留一份成员。l虚基类是在派生类派生类的声明过程的声明过程中声明的,一般形式为:class 派生类名:virtual 继承方式 基类名 派生类的定义;76class Apublic:int a;void display()coutaa=7;p只能访问只能访问objb中基中基类成员类成员a,而不能访,而不能访问问objb 中新增加的中新增加的成员成员b。83l类的组合:在一个类中以另一个类的对象作为数据成员。5.8 继承与组合继承与组合class Teacher private:int num;string name;class BirthDate private:int year,month,day;class Professor:public Teacher private:BirthDate birthday;基类基类/其他类其他类84l继承继承建立了派生类与基类之间的一种“是是”的关系,是纵向的纵向的。l组合组合建立了成员类和组合类(复合类)之间的一种“有有”的关系,是横向的横向的。5.8 继承与组合继承与组合85总结总结l本章主要讲授内容继承和派生的概念派生类的声明方法派生类的构成和成员的访问属性派生类构造函数和析构函数多重继承基类与派生类的转换继承与组合86目标目标l理解派生和继承的相关概念;l掌握派生类的声明方式l掌握派生类的构成和成员的访问属性;l掌握派生类构造函数和析构函数的使用方法;l掌握多重继承的方法;l理解基类和派生类的转换方法;l理解继承与组合的含义。87练习练习l课后第七、八题l以点(point)类为基类,派生类圆类,圆由圆心和半径定义。派生类操作判断任一坐标点是在图形内,还是在图形的边缘上,还是在图形外。88