第6章继承 派生类ppt课件_第1页
第6章继承 派生类ppt课件_第2页
第6章继承 派生类ppt课件_第3页
第6章继承 派生类ppt课件_第4页
第6章继承 派生类ppt课件_第5页
已阅读5页,还剩63页未读 继续免费阅读

下载本文档

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

文档简介

1、C+面向对象程序设计教学内容 第1章 C+概述第2章 类和对象第3章 面向对象程序设计概述第4章 进一步学习类和对象第5章 堆与复制构造函数第6章 继承性:派生类第7章 运算符重载第8章 虚函数和多态性第9章 模板第10章 类库和C+的标准模板库STL第11章 输入输出流第12章 异常处理第6章 继承性:派生类6.1 派生类的概念6.2 单继承6.3 派生类的构造函数和析构函数6.4 多重继承6.5 赋值兼容规则6.6 应用举例6.1 派生类的概念 保持已有类的特性而构造新类的过程称为继承。 在已有类的基础上新增自己的特性而产生新类的过程称为派生。 被继承的已有类称为基类或父类)。 派生出的新

2、类称为派生类或子类)。继承与派生问题举例圆圆矩形矩形几何形状几何形状继承与派生的目的 继承的目的:实现代码重用。 派生的目的:当新的问题出现,原有程序无法解决或不能完全解决时,需要对原有程序进行改造。 C+中类的继承层次自然地表达了人们分析问题时所用的分类结构。大大改善了软件系统的可理解性和可维护性。 派生类的声明class 派生类名:访问权限 基类名1, . 成员定义;多继承:一个派生类有多个基类;单继承:一个派生类只有一个基类。派生类的例子Class Student int number; char *name; float score;public: Student(int number

3、1, char* name1, float score1); void modify(float score1); void print( );派生类的例子续)class Ustudent:public Student char major; /专业public: Ustudent(int number1, char *name1, char *major, float score1); void print( );/ Ustudent 为大学生类派生类基类继承方式 共有三种继承方式:公有继承public),私有继承private),保护继承protected)。 继承方式指定派生类成员以及类

4、外对象对继承来的成员的访问权限。 不同继承方式的影响主要体现在: 1、派生类成员对基类成员的访问控制。 2、派生类对象对基类成员的访问控制。公有派生 (public) 当被继承的基类的访问说明符是public的时候,所有基类的公共成员都成为派生类的公共成员。 派生类中的成员函数可以直接访问基类中的public,但不能访问基类的private成员。 派生类的对象只能访问基类的public成员。私有派生(private) 基类的所有公共成员都成为派生类的私有成员。 派生类中的成员函数可以直接访问基类中的public成员,但不能访问基类的private成员。 派生类的对象不能访问基类中的任何成员。p

5、rotected 关键字的引入 无论基类被怎样继承,基类中的私有成员都不能被其导出类直接访问。只能通过公共接口访问。 继承来的特性不能使用似乎于理不通,但是派生类不加限制的访问基类的私有成员,将破坏基类的封装性,这是面向对象方法中有争议的问题之一。(两难问题) C+中引入了保护段(protected)的概念,这样可以让用户根据需要灵活地加以限制。protected 关键字 派生类的成员函数不能直接访问基类的私有private成员。但派生类的成员函数能访问基类的被保护protected成员。 除了基类的被保护成员对于基类的任何派生类成员都是可访问的以外,protected 访问说明符与priva

6、te说明符是完全等效的。保护继承(protected) 基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可访问。 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。 派生类的对象不能访问基类中的任何成员。6.2 单继承 派生类只有一个基类的时称为单继承。 单继承时类层次为树形结构工具车轿车面包车小汽车卡车旅行车汽车汽车交通工具交通工具单继承的例子/ string.hpp class String private: static int maxLength; char*

7、content; int length; public: String(); String(char*); String(String&); String(); String& operator=(char*); String& operator=(String&); int GetLength(); char* GetContent(); . ;/ editstring.hpp class EditString : public String private: int cursor; public: EditString(char *); EditString

8、(EditString); EditString(); int GetCursor(); void MoveCursor(int i); void Insert(char*); void Insert(String&); void Replace(char*); void Replace(String&); void Delete(int n); ;单继承的例子续)#include “editstring.hpp”main( ) String s1(“abc”); EditString s2(“this is a string.”); char str20; strcpy(st

9、r, s2.GetContent(); s2.MoveCursor(4); s2.Delete(5); s2.MoveCursor(6); s2.Insert(“ is “); s2.Insert(s1); cout“s1=“s1.GetContent( )endl; cout“s2=“s2.GetContent( )endl;StringEditStrings1s2派生类的对象中有一个无名的基类对象多层继承 所谓多层继承是指从一个类派生出一个类,然后又从该派生类派生出另一个类,如此进行下去,直到最后生成的类满足要求为止。 例如: point点) line线) rectangle矩形) 猴猴子

10、子狮子虎猎豹猫猫鸟鸟动动物物6.3 派生类的构造函数和析构函数反。反。派生类的构造函数和析构函数的例子class pointchar c;public:point(char ch)c=ch;void DrawPoint()coutc;class line:public pointint length;public:line(char ch,int i):point(ch) length=i; void DrawLine()length=(length80?80:length);for(int i=0;ilength;i+)DrawPoint();coutendl;一个参数传递链 :将参数传递给

11、基类的构造函数派生类的构造函数和析构函数的例子续)class rectangle : public lineint width;public:rectangle(char ch,int i,int j) : line(ch,i) width=j; void DrawRect()width=(width25?25:width);for(int i=0;iwidth;i+)DrawLine( );一个参数传递链 :将参数传递给基类的构造函数派生类的构造函数和析构函数的例子续)void main()rectangle A(X,30,10);A.DrawRect();/ getch( );继承是重用的

12、基础 面向对象的程序设计中通过继承实现重用reuse便于重用,扩大。 可以在原有的基础上扩充,不修改原有代码。 即使原来的代码完全不符合当前的要求,也不必修改原有的代码。可以只增加新的代码来实现新的功能。覆盖与支配规则 函数覆盖:函数覆盖: 在派生类中可以重新定义基在派生类中可以重新定义基类中已定义的同名函数,我们称之类中已定义的同名函数,我们称之为函数覆盖。为函数覆盖。 支配规则:支配规则: 派生类的对象引用某函数时,编译派生类的对象引用某函数时,编译器先在派生类中找与该函数完全匹器先在派生类中找与该函数完全匹配的函数,有则调用之;配的函数,有则调用之; 否则到其基类中找,依次再到基类否则到

13、其基类中找,依次再到基类的基类中找,的基类中找,等等,若都没有等等,若都没有找到则出错。找到则出错。 若第一次遇到了同名函数但参数不若第一次遇到了同名函数但参数不匹配,则对其进行类型转换后再调匹配,则对其进行类型转换后再调用之,若无法转换则出错。用之,若无法转换则出错。函数覆盖的例子函数覆盖的例子#include #include class person char name10;int age;public:person()age=0;void set(int i,char *str)age=i;strcpy(name,str);void display( )coutname is age

14、years old.endl;函数覆盖的例子续)函数覆盖的例子续)class student : public personint math, chinese, english;public:student( ) math=chinese=english=0; void SetScore(int i,int j,int k)math=i; chinese=j; english=k;void display()coutThe students score is: endlmath: mathendlchinese: chineseendlenglish: englishendl;函数覆盖的例子续

15、)函数覆盖的例子续)void main(void)student st;st.set(15,Wang);st.SetScore(88,85,90);st.person:display();st.display();第四章 继承性:派生类4.1派生类的概念4.2单继承4.3多继承4.4赋值兼容规则4.5应用举例6.4 多继承从两个以上的基类派生出新类,例如:class 派生类名:继承方式1 基类名1,继承方式2 基类名2,.派生类的成员定义;注意:每一个“继承方式”,只用于限制对紧随其后之基类的继承。多继承举例class A public: void setA(int); void showA(

16、); private: int a;class B public: void setB(int); void showB();private: int b;class C : public A, private B public: void setC(int, int, int); void showC(); private: int c;void A:setA(int x) a=x; void B:setB(int x) b=x; void C:setC(int x, int y, int z) SetA(x); /派生类成员直接访问 SetB(y); /基类的公有成员 c=z;/其它函数实

17、现略int main() C obj; obj.setA(5); obj.showA(); obj.setC(6,7,9); obj.showC( ); obj.setB(6); / 错误,私有继承 obj.showB( ); /错误,私有继承 return 0;多继承与单继承C+的多继承可以看成由多个单继承形成的,这样以来,除了每个派生类的实例对象中包含所有的基类的无名对象外,它与单继承并无区别。多继承的构造函数 同单继承一样,多继承的派生类要在其构造函数中激活所有的基类的构造函数。 调用次序: 先基类,后派生类;基类的调用次序以派生类定义中所声明的基类的出现顺序而定。 例:ABDFEC内存

18、对象分布图示意性定义为:示意性定义为:class A ;class B ;class C ;class D:public B,public A ;class E:public C ;class F:public D,public E ;构造函数的调用次序为:构造函数的调用次序为:A、B、D、C、E、FFFDEDABABECC基类与派生类的对应关系 单继承 派生类只从一个基类派生。 多继承 派生类从多个基类派生。 多重派生 由一个基类派生出多个不同的派生类。 多层派生 派生类又作为基类,继续派生新的类。多继承引入的二义性问题举例class B public: int b;class B1 : p

19、ublic B private: int b1;class B2 : public B private: int b2;class C : public B1,public B2 public: int f( ); private: int d;BB1B2C下面的访问是二义性的:C c;c.bc.B:b下面是正确的:c.B1:bc.B2:b二义性问题举例续)bb1bb2dB类子对象B类子对象B1类子对象B2类子对象C类对象由于派生类的对象中多次包含了某个基类的对象,从而产生了二义性。派生类C的对象的存储结构示意图二义性问题解决方案:虚基类class B private: int b;class

20、 B1 : virtual public B private: int b1;class B2 : virtual public B private: int b2;class C : public B1, public B2 private: float d;下面的访问是正确的:C d;d.b;为了对祖先类只继承一次,C+引入了虚基类的概念。BB1B2Cb1b2dB1类子对象B2类子对象C类对象bB类子对象虚基类的派生类对象存储结构示意图虚基类的例子class basepublic:int i;class derived1:virtual public basepublic:int j;cl

21、ass derived2:virtual public basepublic:int k;Inherit base as virtual.Inherit base as virtual, here too.class derived3:public derived1,public derived2public:int product( )return i*j*k;main( )derived3 ob;ob.i=10; / unambiguous because only one copy presentob.j=3;ob.k=5;coutProduct is duct()print

22、1( );/正确,可以调用基类继承的成员 ptr-print2( );/错误,不能访问派生类的成员实例赋值兼容举例B0类void display();B1类void display( );D1类void display( );#include class B0public:void display()coutB0:display()endl;class B1:public B0public:void display( )coutB1:display()endl;class D1:public B1public:void display( )coutD1:display()display( );

23、void main( )B0 b0;B1 b1;D1 d1;B0 *p;p=&b0;fun(p);p=&b1;fun(p);p=&d1;fun(p);执行结果:B0:display( )B0:display( )B0:display( )赋值兼容举例续)以后我们会看到运行时的多态就是通过基类对象的指针指向派生类对象来实现的6.6 应用举例 人员管理系统: 有三类人员:经理、技术人员、推销人员,还有销售经理。 月薪:经理:8000元/月;技术人员:100元/小时;推销人员:4%提成;销售经理:5000元月+5%提成。应用举例 类设计 基类:employee 派生类:tec

24、hnician和salesman 多继承派生类:salesmanagerclass employee protected: char *name; /姓名 int individualEmpNo; /个人编号 int grade; /级别 float accumPay; /月薪总额 static int employeeNo; /本公司职员编号目前最大值 public: employee(); /构造函数 employee(); /析构函数 void pay(); /计算月薪函数 void promote(int); /升级函数 void displayStatus(); /显示人员信息 ;

25、class technician : public employee /技术人员类 private: float hourlyRate; /每小时酬金 int workHours; /当月工作时数 public: technician(); /构造函数 void pay(); /计算月薪函数 void displayStatus(); /显示人员信息;class salesman:virtual public employee /兼职推销员类 protected: float CommRate; /按销售额提取酬金的百分比 float sales; /当月销售额 public: salesma

26、n(); /构造函数 void pay(); /计算月薪函数 void displayStatus(); /显示人员信息;class manager:virtual public employee /经理类 protected: float monthlyPay; /固定月薪数 public: manager(); /构造函数 void pay(); /计算月薪函数 void displayStatus(); /显示人员信息 ;class salesmanager : public manager,public salesman /销售经理类 public: salesmanager ();

27、/构造函数 void pay(); /计算月薪函数 void displayStatus(); /显示人员信息 ;employee:employee() char namestr50; /输人雇员姓名时首先临时存放在namestr中coutnamestr; name=new charstrlen(namestr)+1;/动态申请用于存放姓名的内存空间 strcpy(name, namestr); /将临时存放的姓名复制到 name individualEmpNo= employeeNo+; /新输人的员工,其编号为目前最大编号加1 grade=1; /级别初值为1accumPay=0.0; /

28、月薪总额初值为0 employee : employee() delete name ; /在析构函数中删除为存放姓名动态分配的内存空间void employee : pay( ) /计算月薪,空函数void employee :promote(int increment) grade += increment ; /晋级,提升的级数由 increment指定void employee : displayStatus( ) /显示人员信息,空函数technician : technician() hourlyRate=100; /每小时酬金100元void technician:pay() c

29、out请输入nameworkHours; accumPay=hourlyRate* workHours; /计算月薪,按小时计酬 cout兼职技术人员name编号individualEmpNo 本月工资accumPayendl;void technician:displayStatus() cout“兼职技术人员”name“编号” individualEmpNo 级别为 grade 级,已付本月工资accumPayendl;salesman:salesman() CommRate=0.04; /销售提成比例4void salesman:pay() cout请输入namesales; accum

30、Pay=sales*CommRate; /月薪销售提成 cout推销员name编号individualEmpNo 本月工资accumPayendl;void salesman:displayStatus() cout推销员name编号individualEmpNo 级别为grade级,已付本月工资accumPayendl;manager:manager() monthlyPay=8000; /固定月薪8000元void manager : pay() accumPay=monthlyPay; /月薪总额即固定月薪数 cout经理name编号individualEmpNo 本月工资accumPayendl;void manager : displayStatus() cout经理name编号individualEmpNo 级别为grade级,已付本月工资accumPayendl;salesmanager :salesmanager()

温馨提示

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

评论

0/150

提交评论