收藏 分享(赏)

面向对象分析与设计chapter4.ppt

上传人:dzzj200808 文档编号:3347621 上传时间:2018-10-16 格式:PPT 页数:38 大小:323KB
下载 相关 举报
面向对象分析与设计chapter4.ppt_第1页
第1页 / 共38页
面向对象分析与设计chapter4.ppt_第2页
第2页 / 共38页
面向对象分析与设计chapter4.ppt_第3页
第3页 / 共38页
面向对象分析与设计chapter4.ppt_第4页
第4页 / 共38页
面向对象分析与设计chapter4.ppt_第5页
第5页 / 共38页
点击查看更多>>
资源描述

1、第4章 继承性与派生类,本章的学习目的客观事物姿态万千、层出不穷,新事物在继承旧事物基本属性的基础上增添新的内容,使客观世界更加丰富多彩。作为模拟人们理解和处理客观世界思维方式的面向对象技术,它也提供了继承的机制,使继承性成为了 C+面向对象技术的最重要的基本特征。即C+面向对象技术将事物抽象成类,允许利用已有类定义新的类,并将类组织成合理的层次结构,以精确地描述客观事物之间的联系。 C+的这种继承机制为编程人员提供了重复利用程序资源的一种途径,编程人员可以扩充和完善旧的程序以适用新的需求,可用继承机制实现代码重用和代码扩充,大大提高程序的开发效率。,因此,我们在前面学习了类的定义和构造设计的

2、基础上,应该进一步研究类之间的关系,特别地应该学习类之间的继承性和派生性,以全面掌握C+面向对象程序设计方法。本章的学习内容 继承的概念 派生类的定义 派生类的构造函数和析构函数 继承属性的访问权限控制 多继承的概念,类的继承:就是根据一个类创建一个新类的过程。 类的派生:从已有类产生新类的过程就是类的派生。 通常将用来派生新类的类称为基类(或父类),而将派生出来的新类称为派生类 (或子类)。 新类自动具有已有类的所有成员,并可根据需要添加更多的成员。,4.1 继承、派生和类的层次关系,4.2 派生类,派生类是在继承基类的属性和操作的基础上增添新的属性和操作而产生的新类。 派生类是基类的特殊子

3、类,基类是抽取派生类的主要属性和操作而得到的抽象描述。派生类继承了基类的所有特性,但不等同于基类,否则就没有派生的必要了。 继承关系体现了特殊与一般的关系。,继承的一个作用就是允许派生类在继承父类共性的基础上,增加新的属性和操作来实现特殊功能;另一个作用是代码重用,从基类派生子类,子类无需修改基类的代码,就可以直接拥有基类的成员,然后增加少量代码就可以实现特殊功能,这就实现了代码的重用。,class :;其中,有三种:公有继承、私有继承和保护继承,分别用关键字public、private和protected表示。缺省情况下为私有继承。,class person /基类 protected:ch

4、ar name11;char sex;int age; public:char* GetName();int GetSex(); int Getage(); ;class Student:public person private:char id9;float score; public:float GetScore(); ;,4.2.1 派生类的定义,【例4.1】 派生类的定义class A /定义一个基类A,A也称为超类、父类 int i;public: void set_i(int n) i=n; int get_i( ) return i; ;class B : public A /下

5、划线处说明类B将继承类A的公有成员 int j;public: void set_j(int n) j=n; int Multiply( ) return j*get_i( ) ; /可调用基类的get_i( ) ; /B不能访问A类的私有成员i。 Main ( ) B ob; ob.set_i(10); /初始化ii,B可通过A类的set_i( )访问i ob.set_j(4); /初始化B中的j coutob. Multiply( ); /运行结果为40 return 0;,派生类的生成包含三个步骤: (1)吸收基类成员吸收基类的部分成员,不吸收构造函数和析构函数。它是一个重用过程。 (2

6、)改造基类成员一是通过派生类定义时的继承方式来控制;二是通过定义同名成员屏蔽基类成员。它是一个扩充过程。,4.2.2 派生类的生成过程,class person /基类 protected:char name11;char sex;int age; public:void Show(); ;class Student:public person private:float score; public:void Show()person:Show();coutscoreendl; ;,(3)添加派生类新成员仅仅继承基类的成员是不够的,需要在派生类中添加新成员,以保证派生类在功能上有所发展。同基类

7、的构造函数和析构函数是不能被继承的,需要加入新的构造函数和析构函数完成一些特别的初始化和扫尾清理工作。,class person /基类 protected:char name11;char sex;int age; public:void Show(); ;class Student:public person private:float score; public:void Show()person:Show();coutscoreendl; ;,4.3 访问权限控制从派生类的定义格式可知,有三种继承方式:公有、私有和保护。因此,派生类对基类成员的访问权限控制也从三个方面考虑:(1)公有继

8、承的访问权限控制;(2)私有继承的访问权限控制;(3)保护继承的访问权限控制;,4.3.1 公有继承的访问权限控制当类的继承方式为公有继承时: (1)在派生类中,基类的公有成员和保护成员被继承后仍然作为派生类的公有成员和保护成员,派生类的成员可以直接访问它们; (2)基类的私有成员无法继承为派生类的私有成员或其他成员,因此派生类的成员无法直接访问基类的私有成员。 (3)在类外,派生类的对象只可以访问继 承下来的基类公有成员。,【例4.1】公有继承的访问权限控制 class A /定义一个基类A,A也称为超类、父类 int i;public: void set_i(int n) i=n; int

9、 get_i( ) return i; ;class B : public A /下划线处说明类B将继承类A的公有成员 int j;public: void set_j(int n) j=n; int Multiply( ) return j*get_i( ) ; /可调用基类的get_i( ) ; /B不能访问A类的私有成员i。 Main ( ) B ob; ob.set_i(10); /初始化i,B可通过A类的set_i( )访问i ob.set_j(4); /初始化B中的j coutob. Multiply( ); /运行结果为40 return 0;,当类的继承方式为私有继承时:(1)

10、在派生类中,基类的公有成员和保护成员被继承以后将作为派生类的私有成员,派生类的成员函数可以直接访问它们;(2)基类的私有成员没有被继承过来,因此派生类的成员无法访问基类的私有成员;(3)在类外,无法访问派生类对象中从基类继承的所有成员。(4) 私有继承之后,基类的成员再也无法在以后的派生类中发挥作用,出于这种原因,一般不使用私有继承方式。,4.3.2 私有继承的访问权限控制,例4-2 私有继承举例#include #include class Person private: char name11;char sex;protected:int age; public:Person(const

11、char* Name,int Age,char Sex);char* GetName() return name;int Getage();int GetSex;,class Student:private Person private:char id9;float score; public:Student(char* pName,int Age,char Sex, char* pId,float Score) void Display(); ; void Student:Display() cout“name:”GetName()t /访问变为私有的基类成 员函数cout“id:”idt;

12、 /直接访问本类私有成员cout“age:”aget; /访问基类的保护成员(变为私有的)cout“score:”scoreendl; void main() Student s2(“wang min”,20,m,”03410102”,80);s2.Display(); ,4.3.3 保护继承的访问权限控制,当类的继承方式为保护继承时: (1) 在派生类中,基类的公有成员和保护成员被继承以后将作为派生类的保护成员,派生类的成员可以直接访问它们; (2)基类的私有成员没有被继承,因此派生类的成员无法访问基类的私有成员。 (3) 在类外,无法访问派生类对象中从基类继承的所有成员。 (4)与私有继承

13、不同的是,保护继承还没有完全终止基类的功能,即保护继承可以传递部分基类成员给派生类的派生类,而私有继承不可以。如果合理地利用保护继承,就可以在类的复杂层次关系中为共享访问与成员隐蔽之间找到一个平衡点,既实现部分成员隐蔽,又能方便部分成员的继承,实现代码的高效重用和扩充。,不论哪种继承方式,派生类新定义成员均不能直接访问基类的私有成员,只能通过基类的公有成员函数或保护成员函数访问基类的私有数据成员,而基类的私有成员函数根本就不会继承,更谈不上使用。所以,除非仅限于本类使用,否则,一般不将成员函数定义为私有成员。,在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须调用基类的构造函数初

14、始化基类的数据成员。如果派生类中还有对象成员时,还应调用对象成员类的构造函数初始化对象成员。 派生类构造函数的一般格式如下: ():(),, (), , () ;,5.4.1 派生类的构造函数,例4-3 派生类构造函数定义举例#include #include class Person private: char name11;char sex;protected:int age; public:Person(const char* Name,int Age,char Sex);char* GetName() return (name);int Getage();int GetSex; ;,c

15、lass Student:public Person private:char id9;float score; public:Student(char* pName,int Age,char Sex, char* pId, float Score): person(pName, Age, Sex) strcpy(id,pId); score=Score; char* GetId(char* pId) return (id); float GetScore() return score;void Display(); ;,使用派生类构造函数时应注意:(1)当基类中没有显式定义构造函数时,派生类

16、构造函数的定义可以省略对基类构造函数的调用,而采用隐含调用。 (2)当基类的构造函数使用一个或多个参数时,派生类必须定义构造函数,提供将参数传递给基类构造函数的途径。这时,派生类构造函数的函数体可能为空,仅起到参数传递的作用。,例4-4 派生类构造函数显式调用基类构造函数的调用顺序。 #include class A public:A() cout“A Constructor1”endl;A(int i) x1=i;cout“A Constructor2”endl; void dispa() cout“x1=“x1endl;private:int x1; ;class B:public A p

17、ublic:B() cout“B Constructor1”endl;B(int i):A(i+10) x2=i; cout“B Constructor2”endl; void dispb() dispa(); /调用基类成员函数cout“x2=“x2endl;private:int x2; ;void main() B b(2); b.dispb(); ,运行结果 A Constructor2 B Constructor2 x1=12 x2=2,4.4.2 派生类的析构函数 由于基类的析构函数也不能被继承,因此,必须定义派生类的析构函数。派生类的析构函数必须通过调用基类的析构函数来做基类的一

18、些清理工作。 调用顺序是: 先调用派生类的析构函数; 再调用对象成员类的析构函数(如果有对象成员); 最后调用基类的析构函数,其顺序与调用构造函数的顺序相反。,例4-8继承方式下构造函数和析构函数的调用顺序 #include class A public:A() cout“A Constructor”endl; A() cout“A Destructor”endl; class B:public A public:B() cout“B Constructor”endl; B() cout“B Destructor”endl; void main() B b; 运行结果:A Constructo

19、rB ConstructorB DestructorA Destructor,4.5 多继承 根据派生类继承基类的个数,将继承分为单继承和多继承。 当派生类只有一个基类时称为单继承,如图(a)和(b)所示;当派生类有多个基类时称为多继承,如图(c)所示。 单继承可以看作是多继承的一个特例,多继承可以看作是多个单继承的组合,它们有很多相同特性。,4.5.1 多继承的定义格式,多继承可以看作是单继承的扩展,派生类与每个基类之间的关系可以看作是一个单继承。在C+中,多继承的定义格式如下:,class : ,;,class window public: window(int top,int left,

20、int bottom,int right); class scrollbar public: scrollbar(int top,int left,int bottom,int right); class scrollbarwind : public window , public scrollbar public: scrollbarwind(int top ,int left ,int bottom ,int right); ;,在多继承方式下,派生类构造函数的定义格式如下:,4.5.2 多继承的构造函数,(): (),() , (), ,() ;,构造函数的调用顺序: 先调用所有基类的构

21、造函数初始化所有基类的数据成员。处于同一层次的各基类构造函数的调用顺序取决于定义派生类时所指定的基类顺序,与派生类构造函数中所定义的成员初始化列表顺序无关。 如果派生类中还有对象成员时,还应调用对象成员类的构造函数初始化对象成员。,例4-9 多继承方式下构造函数和析构函数的调用顺序。 #include class A public:A(int i)a=i; cout“A Constructor”endl; void disp() cout“a=“aendl; A()cout“A Destructor”endl; private:int a; ; class B public:B(int j)b

22、=j; cout“B Constructor”endl; void disp() cout“b=“bendl; B()cout“B Destructor”endl; private:int b; ;,class C: public B,pulic A public:C(int k):A(k+2),B(k-2)c=k; cout“C Constructor”endl; void disp() A:disp();B:disp(); cout“c=“cendl; c()cout“C Destructor”endl; private:int c; void main() C obj(10);obj.d

23、isp(); ,运行结果: B Constructor A Constructor C Constructor a=12 b=8 c=10 C Destructor A Destructor B Destructor,4.5.3 虚基类,在派生类中对基类成员的访问应该是唯一的。但是,在多继承方式下,可能造成对基类中某个成员的访问出现不唯一的情况,称为对基类成员访问的二义性问题,如下图所示。,解决的办法(1)用作用域运算符“:”进行限定;(2)还可以将直接基类的共同基类设置为虚基类,则从不同路径继承过来的该类成员在内存中只拥有一个副本,进而解决了同名成员的唯一标识问题。虚基类的定义格式为:cla

24、ss :virtual ,#include class A public: A() a=10; protected: int a; ; class A1: virtual public A public: A1() coutaendl; ; class A2: virtual public A public: A2() coutaendl; ; class B: A1,A2 public: B() coutaendl; ; void main() B obj; ,习题,1.写出下面程序的运行结果: #include Class A public:A(int i,int j)a=i;b=j)vo

25、id move(int x,int y)a+=x;b+=y;void show()cout“(”a“,”b“)”endl; private:int a,b; ;,class B:public A public:B(int i,int j,int k,int l):A(i,j),x(k),y(l)void show()coutx“,”yendl;void fun() move(3,5); void f1() A:show(); private:int x,y; ;,void main() A aa(1,2);aa.show();B bb(3,4,5,6);bb.fun();bb.A:show()

26、;bb.B:show();bb.f1(); ,2. 写出下面程序的运行结果,并分析总结. #include class Base public:void who()cout“Base class”endl; class Derive1:public Base public:void who() cout“Derive1 class”endl; ; class Derive2:public Base public:void who() cout“Derive2 class”endl; ;,void main() Base obj1, *p;Derive1 obj2;Derive2 obj3;p= ,3.编写一个学生和教师数据输入和显示程序。学生数据有编号、姓名、班号和成绩,教师数据有编号、姓名、职称和部门。要求设计这两个类的一个基类person,使之包含编号和姓名这两个属性和显示编号和姓名的操作函数。(实验题),

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报