《继承和派生类》PPT课件.ppt_第1页
《继承和派生类》PPT课件.ppt_第2页
《继承和派生类》PPT课件.ppt_第3页
《继承和派生类》PPT课件.ppt_第4页
《继承和派生类》PPT课件.ppt_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

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

文档简介

第10章 继承和派生类,目的与要求 10.1 继承与派生 10.2 冲突、支配规则和赋值兼容性 10.3 虚基类 10.4 静态数据成员 本章小结,目的与要求,通过本章学习,应理解继承与派生的概念,掌握派生类的定义语句格式及使用方法。知道基类成员经公有或私有派生后在派生类中的访问权限。初步掌握冲突、支配规则、赋值兼容性的概念。了解虚基类的概念、虚基类的语句定义格式及使用方法。了解静态成员的定义格式、初始化方式及作用域。,10.1 继承与派生,继承:从已有类出发建立新的类,使新类部分或全部地继承已有类的成员。 派生:通过继承已有的一个或多个类产生一个新类称为派生。,10.1.1 继承与派生的基本概念,1继承与派生的定义 在定义类B时,若使用类A的部分或全部成员,则称类B继承了类A,并称类A为基类或父类,称类B为派生类或子类。基类与派生类或父类与子类的关系可以用图表示。,2单一继承,若派生类是由一个基类派生出来的,称为单一继承,如派生类Score是由一个基类Student派生出的,所以为单一继承。如图所示。,3多重继承,若派生类由多个基类派生出,称为多重继承。如图所示。,10.1.2 派生类的定义,1.定义派生类的格式 class : , ; 说明: (1)派生类由n个基类多重派生,当n=1时为单一继承。 (2)访问权限access=public、private与protected,2公有派生,若在定义派生类时,access为public,则定义公有派生。公有派生时,基类中所有成员在派生类中保持各个成员的访问权限。具体访问权限如下: (1)基类中public成员在派生类仍保持为public成员,所以在派生类内、外都可直接使用这些成员。 (2)基类中private成员属于基类私有成员,所以在派生类内、外都不能直接使用这些成员。只能通过该基类公有或保护成员函数间接使用基类中的私有成员。,公有派生,(3)基类中protected成员可在派生类中直接使用,但在派生类外不可直接访问这类成员,必须通过派生类的公有或保护成员函数或基类的成员函数才能访问。 【例10.1】 用学生档案类Student派生出学生成绩类Score。讨论基类中公有、私有与保护数据成员在派生类中访问权限的变化。,例程,3私有派生,若在定义派生类时,access为private则定义了私有派生。经过私有派生后: (1)基类中公有成员在派生类变为私有成员,在派生类内可以使用,而在派生类外不能直接使用。 (2)基类中保护成员在派生类变为私有成员,在派生类内可以使用,而在派生类外不能直接使用。 (3)基类中私有成员在派生类内、外都不能直接使用,必须通过基类公有函数使用。,10.1.3 派生类的构造函数与基类成员的初始化,1.派生类构造函数格式 派生类的构造函数由初始化基类数据成员构造函数与初始化派生类新增的数据成员构造函数组成。派生类构造函数的格式为: :(形参表):(实参表1),(实参表n) 派生类构造函数体,派生类构造函数格式,说明: (1)基类构造函数实参可以是表达式或派生类构造函数的形参。 (2)实参只与形参名有关,而与参数顺序无关。 (3)冒号后基类构造函数列表称为初始化成员列表。,派生类构造函数举例,【例10.2】多重派生实例。定义描述圆的 类Circle,定义描述高的类High,用描述圆 的类与描述高的类作为基类,多重派生出 圆柱体类Cylinder。讨论多重继承中基类成 员的初始化问题。 例程,2建立对象时,构造函数的调用顺序,先调用基类构造函数,再调用派生类构造函 数。注意: (1)在派生类中并不能直接对基类的私有数据成 赋初始值,必须通过公有的构造函数进行初始化工作。 (2)基类构造函数的调用顺序取决于它们在派生类 中说明顺序,而与它们在派生类构造函数中的顺序无关。,3撤消对象时,析构函数的调用顺序,在撤消派生类的对象时,析构函数的调用顺 序正好与构造函数的顺序相反。即:先调用派生 类的析构函数,再调用基类析构函数。 【例10.3】定义两个基类Base1与Base2,并由Base1与Base2派生出派生类Derive。编写程 序,输出派生类中构造函数与析构函数的调用关 系。 例程,4派生类中包含对象成员的构造函数,若派生类中包含对象成员,则在派生类构造函数的 初始化成员列表中不仅要列举要调用的基类构造函数, 而且要列举调用的对象成员构造函数。 【例10.4】将例10.3的派生类改为包含对象成员的派生类。 例程 首先要调用基类的构造函数,再调用对象成员的构 造函数,最后执行派生类的构造函数。在有多个对象成 员的情况下,调用这些对象成员的构造函数的顺序取决 于它们在派生类中说明顺序。,10.2 冲突、支配规则和赋值兼容性,10.2.1冲突 引例: 【例10.5】在例10.2中将描述高的类改为描述矩形的类Rectangle,在Rectangle类中用矩形中心坐标(x,y)、高(High)与宽(Width)作为类的数据成员。 例程 冲突:派生类使用基类中同名成员时出现不惟一称为冲突。 解决方法:使用作用域运算符“:”指明同名成员属于哪一个基类,即: :,冲突,结论: 若一个公有派生类是由两个或多个基类派生,当基类中成员的访问权限为public或protected且不同基类中的成员同名时,派生类使用到基类中的同名成员时出现不惟一性称为冲突。 解决方法是使用作用域运算符指明发生冲突的成员属于哪个基类。,10.2.2 支配规则,所谓支配规则是指,当派生类中成员与基类中成员同名时,在不用作用域运算符时,派生类成员名优于基类成员名。 【例10.6】在【例10.5 】的派生类Cylinder中,新增数据成员(x,y,z)表示圆柱体中心坐标。并从基类Rectangle中删除(x,y)。 例程 注意:当派生的成员名与基类的成员名相同时,在派生类中或派生类外要使用基类中的这种成员时,仍要使用作用域运算符。,10.2.3 赋值兼容规则,公有派生类的对象可赋给其基类对象, 基类对象不能赋给派生类对象的规则,称 为赋值兼容规则。,10.2.4 基类和对象成员的几点说明,(1)任一基类在派生类中只能继承一次。 (2)基类成员与对象成员在使用上的差别 派生类中可直接使用基类的成员(访问权限 允许的话); 使用对象成员时,必须在对象名后加上成员运算符“.”和成员名。,10.3 虚基类,10.3.1 多重派生的基类拷贝 若类B与类C由类A公有派生,而类D由类B与类C公有派生,则类D中将包含类A的两个拷贝(如图所示)。这种同一个基类在派生类中产生多个拷贝不仅多占用了存储空间,而且可能会造成多个拷贝数据的不一致。,多重派生的基类拷贝,【例10.7】一个公共基类在派生类中产生两个拷贝。 例程 如果在多条继承路径上有一个公共的基类,则该基类会在这些路径中的某几条路径的汇合处产生几个拷贝。为使这样的公共基类只产生一个拷贝,须将该基类说明为虚基类。,10.3.2 虚基类,在多重派生的过程中,欲使公共的基类在派生中只 有一个拷贝,可将此基类说明成虚基类。 虚基类的定义格式为: class :virtual ; 或 class : virtual ; 【例10.8】定义虚基类,使派生类中只有基类的一个拷贝。例程,10.4 静态数据成员,将类的某一个数据成员的存储类型定义为静 态类型时,则由该类所产生的所有对象均共享为 静态成员所分配的一个存储空间。,(1)静态数据成员的定义与引用方法,在类中对静态数据成员作引用性说明 static ; 在类外文件作用域对静态数据成员作定义性说明 必须在类外的文件作用域中,且只能作一次定义性说明,并分配 内存空间。 :=初值; 定义性说明时,静态数据成员缺省初值为0。 静态数据成员引用格式 :,静态数据成员,(2)同类不同对象的静态数据成员占用相同的 存储空间 。 (3)静态数据成员置初值不受访问权限的限制。 (4)为了保持静态数据成员取值的一致性,通 常在构造函数中不给静态数据置初值,而是在静 态数据成员的定义性说明时指定初值。,本章小结,1.继承 继承:从已有类出发建立新的类,使新类部分或全部地继承已有类的成员称为继承。 派生:通过继承已有的一个或多个类产生一个新类称为派生。 派生类的定义格式如下: class :, 派生类体;,基类成员在派生类中访问权限,公有或私有派生后基类成员在派生类中访问权限,派生类构造函数和析构函数,因为派生类成员由基类成员与派生类中新增加的成员组成,所以初始化工作应分为对派生类中新增成员的初始化与基类成员的初始化。由于初始化工作是由构造函数完成的,所以初始化基类成员的工作是由派生类的构造函数来完成的。 派生类构造函数的格式如下: :(形参表):(实参表1) (实参表n) ; 构造函数的调用顺序是先基类后派生类,析构函数的调用顺序是先派生类后基类。,2冲突、支配和赋值兼容性,冲突:派生类使用基类中同名成员时出现不唯一称为冲突。冲突的解决方法: : 支配规则:使用派生类中与基类中同名成员时,派生类成员优于基类同名成员的规则称为支配规则。 赋值的兼容性:派生类对象可赋值给基类对象,基类对象不能赋给派生类对象称为赋值的兼容性。,3虚基类,在多重派生的过程中,欲使公共的基类在 派生类中只有一个拷贝,可将此基类说明成虚 基类。虚基类的定义格式为: class :virtual ; 或 class : virtual ;,4静态数据成员,静态数据成员的定义必须分两步完成,在类内作引用性说明,在类外作定义性说明。说明与引用格式为: 类内作引用性说明的格式: static ; 类外作定义性说明的格式: :=初值; 引用格式: :,例10.1(1),# include class Student private: int No; /定义No为私有数据成员 protected: int Age; /定义Age为保护的数据成员 public: char Sex; /定义Sex为公有数据成员 Student(int no,int age,char sex) /定义类Student的构造函数 No=no;Age=age;Sex=sex; int GetNo( ) return No; /返回No的公有成员函数 int GetAge( ) return Age; /返回Age的公有成员函数 void ShowS( ) /显示No、Age、Sex的公有成员函数 cout“No=“Not“Age=“Aget“Sex=“Sexendl; ;,例10.1(2),class Score : public Student /由基类Student公有派生出子类Score private: int Phi,Math; /定义类Score的私有数据成员 public: Score(int n,int a,char s,int p,int m):Student(n,a,s) /类Score的构造函数 Phi=p;Math=m; void Show( void) /显示类Score与其父类Student的数据成员值 cout“No=“GetNo( )t“Age=“Aget“Sex=“Sex t“Phi=“Phit“Math=“Mathendl; ;,例10.1(3),void main(void) Score s (101,20,M,90,80); /用类Score定义一个对象s s.ShowS( ); /类Score的对象s调用基类公有函数 ShowS() s.Show( ); /类Score的对象调用公有函数Show() cout“No=“s.GetNo( )t“Age=“s.GetAge()t“Sex=“s.Sexendl; 程序执行后输出: No=101 Age=20 Sex=M No=101 Age=20 Sex=M Phi=90 Math=80 No=101 Age=20 Sex=M,返回,例10.2(1),# include class Circle /定义描述圆的类,其中(x,y)为圆心,r为半径 protected: float x,y,r; public: Circle(float a,float b,float c) x=a;y=b;r=c; ; class High /定义描述高的类 private: float h; public: High(float a) h=a; float Geth( ) return h; ;,例10.2(2),class Cylinder:public Circle,private High /由圆与高派生出圆柱体类 private: float Volume; public: Cylinder(float a,float b,float c,float d):Circle(a,b,c),High(d) /D Volume=r*r*3.1415*Geth( ); /E void Show() cout“x=“xt“y=“yt“r=“rt “h=“Geth()t“V=“ Volumeendl; ;,例10.2(3),void main (void) Cylinder cy(3,3,2,10); cy.Show(); 程序执行后输出: x=3 y=3 r=2 h=10 V=125.664 返回,例10.3(1),# include class Base1 /定义基类Base1 private: int x; /定义基类Base1的私有数据成员x public: Base1(int a) /基类Base1的构造函数 x=a; cout“调用基类1的构造函数!“endl; Base1( ) /基类Base1的析构函数 cout“调用基类1的析构函数!“endl; ;,例10.3(2),class Base2 /定义基类Base2 private: int y; /定义基类Base2的私有数据成员y public: Base2(int a) /基类Base2的构造函数 y=a; cout“调用基类2的构造函数!“endl; Base2( ) /基类Base2的析构函数 cout“调用基类2的析构函数!“endl; ;,例10.3(3),class Derive:public Base1,public Base2 /派生类Derive private: int z; /派生类Derive新增的私有数据成员 public: Derive(int a,int b):Base1(a),Base2(20) /派生类Derive构造函数 z=b; cout“调用派生类构造函数!“endl; Derive( ) /派生类Derive的析构函数 cout“调用派生类的析构函数!“endl; ; void main(void) Derive c(100,200);,例10.3(4),程序执行后输出: 调用基类1的构造函数! 调用基类2的构造函数! 调用派生类的构造函数! 调用派生类析构函数! 调用基类2的析构函数! 调用基类1的析构函数! 返回,例10.4(1),class Derive:public Base1,public Base2 private: int z; Base1 b1,b2; /在派生类中定义基类对象成员b1,b2 public: Derive (int a,int b):Base1(a),Base2(20),b1(200),b2(a+b) /定义构造函数 z=b; cout“调用派生类的构造函数!“endl; Derive ( ) cout“调用派生类的析构函数!“endl; ; void main(void) Derive d(100,200);,例10.4(2),执行程序后输出: 调用基类1的构造函数! 调用基类2的构造函数! 调用基类1的构造函数! 调用基类1的构造函数! 调用派生类的构造函数! 调用派生类的析构函数! 调用基类1的析构函数! 调用基类1的析构函数! 调用基类2的析构函数! 调用基类1的析构函数! 返回,例10.5(1),# include class Circle /定义描述圆的基类 protected: float x,y,r; /(x,y)为圆心,r为半径 public: Circle(float a,float b,float c) x=a;y=b;r=c; float Area( ) return (r*r*3.14159); /计算圆的面积 ;,例10.5(2),class Rectangle /定义描述矩形的基类 protected: float x,y,h,w; public: Rectangle(float a, float b, float c, float d) x=a;y=b;h=c;w=d; float Area(void) /计算矩形面积 return h*w; ;,例10.5(3),class Cylinder:public Circle,public Rectangle /描述一个圆柱体的派生类 private: float Volume; /圆柱体的体积 public: Cylinder(float a,float b,float c):Circle(a,b,c),Rectangle(10,10,c,c) /A Volume=Area( )*h; /B float GetV( )return Volume; void Show(void) cout“x=“xt“y=“yendl; /C ;,例10.5(4),void main (void) Cylinder cy(3,3,2); cy.Show(); cout“Volume=“cy.GetV()endl; 程序执行后输出: x=3 y=3 Volume=25.1327 返回,例10.5(5),# include class Circle /定义描述圆的基类 protected: float x,y,r; /(x,y)为圆心,r为半径 public: Circle(float a,float b,float c) x=a;y=b;r=c; float Area( ) return (r*r*3.14159); /计算圆的面积 ;,例10.5(6),class Rectangle /定义描述矩形的基类 protected: float x,y,h,w; public: Rectangle(float a, float b, float c, float d) x=a;y=b;h=c;w=d; float Area(void) /计算矩形面积 return h*w; ;,例10.5(7),class Cylinder:public Circle,public Rectangle /描述一个圆柱体的派生类 private: float Volume; /圆柱体的体积 public: Cylinder(float a,float b,float c):Circle(a,b,c),Rectangle(10,10,c,c) /D Volume=Circle:Area( )*h; /E float GetV( )return Volume; void Show(void) cout“x=“Circle:xt“y=“Circle:yendl; /F ;,例10.5(8),void main (void) Cylinder cy(3,3,2); cy.Show(); cout“Volume=“cy.GetV()endl; 程序执行后输出: x=3 y=3 Volume=25.1327 返回,例10.6(1),# include class Circle /定义描述圆的基类,其中(x,y)为圆心,r为半径 protected: float x,y,r; public: Circle(float a,float b,float c) x=a;y=b;r=c; float Area( ) return (r*r*3.14159); /计算圆的面积 ; class Rectangle /定义描述矩形的基类 protected: float h,w; public:,例10.6(2),Rectangle(float c, float d) h=c;w=d; float Area(void) /计算矩形面积 return h*w; ; class Cylinder:public Circle,public Rectangle /描述一个圆柱体的派生类 private: float x,y,z,Volume; /圆柱体的中心坐标与体积 public: Cylinder(float a,float b,float c,float d):Circle(a,b,d),Rectangle(d,d) x=a;y=b;z=c; Volume=Circle:Area( )*h; ,例10.6(3),float GetV( ) return Volume; void Show(void) cout“x=“xt“y=“y t“z=“z endl; ; void main (void) Cylinder cy(3,3,3,2); cy.Show(); cout“Volume=“cy.GetV()endl; 程序执行后输出: x=3 y=3 z=3 Volume=25.1327 返回,例10.7(1),# include class A public: int x; A( int a) x=a; ; class B:publi

温馨提示

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

评论

0/150

提交评论