面向对象程序设计语言c++-第6章继承和派生

上传人:j****9 文档编号:54644416 上传时间:2018-09-16 格式:PPT 页数:39 大小:754KB
返回 下载 相关 举报
面向对象程序设计语言c++-第6章继承和派生_第1页
第1页 / 共39页
面向对象程序设计语言c++-第6章继承和派生_第2页
第2页 / 共39页
面向对象程序设计语言c++-第6章继承和派生_第3页
第3页 / 共39页
面向对象程序设计语言c++-第6章继承和派生_第4页
第4页 / 共39页
面向对象程序设计语言c++-第6章继承和派生_第5页
第5页 / 共39页
点击查看更多>>
资源描述

《面向对象程序设计语言c++-第6章继承和派生》由会员分享,可在线阅读,更多相关《面向对象程序设计语言c++-第6章继承和派生(39页珍藏版)》请在金锄头文库上搜索。

1、面向对象程序设计语言C+,电子科技大学示范性软件学院,1,第六章 继承和派生,C+的类提供了良好的模块分解技术,也具有可重用软件所期望的品质:它们是相似一致的模块,通过信息隐藏,将它们的接口和实现清楚地分开来。但是,仅有这些是不够的,我们还希望在类的基础上能取得更好的可重用性和可扩充性的目标。 面向对象的继承技术提供了实现上述目标的有力手段。,2,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 在自然界中,继承这个概念是非常普遍的。小猫仔继承了猫爸猫妈的特性,所以长得是猫鼻子猫眼,我们不会把它错认为是小狗。继承就是这样,会将一些本质的特性遗传给子代,使子代在很大程度上具有与

2、父代相同的性质。当然,子代同时还具有父代没有的特性。 下面的两张图显示了两种不同的分类情况:,3,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承,4,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承,5,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 在最简单的情况下,一个类B继承类A或者从类A派生类B,通常将类A称为基类(父类),类B称为派生类(子类)。这时,类B的对象具有类A对象的所有特性,甚至还会更多一些。也可以这样说,类B从类A派生出来。这意味着类B至少描述了与类A同样的接口,至少包含了同类A一样的数据,可以共享类A的成员函数。

3、例61说明了类A与类B之间的这种关系。,6,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承,7,class A public:int pubA; pirvate:int priA; ;,class B : public A public:int pubB; private:int priB; ; (例6-1),第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 继承就是从先辈处得到属性和行为特征。类的继承,是新的类从已有的类获取已有的特征;换个说法就是从已有类产生新类的过程就是派生。类的派生实际是通过扩展、更改和特殊化,从一个已知类建立一个新类的过程。通过类

4、的派生,可以建立具有共通关键特征的对象家族,从而实现父类代码的重用,这种继承和派生机制对于已有程序的发展和改进是极为有力的。可以描述基类和派生类的关系为:派生类是基类的具体化,基类是派生类的抽象。即基类综合了派生类的公共特征,派生类则在基类的基础上增加了某些特征,把抽象类变成具体的、实用的类型。,8,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 那么,派生类定义的成员能否与基类的成员同名呢? C+允许派生类可以重新定义基类的成员。如果派生类定义了与基类同名的成员,称派生类的成员覆盖了基类的同名成员。如果要在派生类中使用基类的同名成员,可以显式地使用下述类名限定符: 类名:

5、成员 来使用基类的成员。(例6-3),9,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 一个派生类从外部看,非常类似一个基类,但内部则有不同。特别地,一个派生类没有权力访问它的基类的私有数据,就像其他任何类一样。起初一看,这似乎太严格了,然而以正确的方式考察,这样做的确有意义,一个类的私有成员对其他类(包括派生类) 不可访问的原因是确保没有其他类的成员函数依赖它们。这就允许软件适应未来的改变,赋予面向对象方法以更大的能力。,10,第六章 继承和派生,6.1派生类的概念 6.1.1为什么要使用继承 派生类的生成过程包括如下三步: (1)继承基类的所有成员:将基类成员全盘吸收

6、。这样,派生类实际上包含了他所有基类中除了构造和析构函数之外的所有成员; (2)改造基类成员:一个通过不同的派生方式改造基类成员的访问控制问题;第二个方法就是在派生类中声明一个和基类成员同名的成员覆盖基类成员进行改造; (3)增加新的成员:根据派生类的实际特征,增加不同于基类的成员。,11,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式C+中,派生类的一般语法形式为class 派生类名 : 基类类名, 基类类名, ; 其中: “:”后面罗列的是基类类名表,它是由“,”隔开一串元素,每个元素都是“ 基类类名”。 表示访问描述符,称为为派生方式。派生方式有私有派生(当为

7、private或缺省时),公有派生(当为public)和保护派生(当为protected)等三种。,12,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 1公有派生 在公有派生情况下,基类保护成员和公有成员的访问权限在派生类中保持不变。即 基类的保护成员在派生类中仍然是保护成员 基类的公有成员在派生类中仍然是公有成员 基类的私有成员在派生类中成为派生类的不可访问成员 (例6-4),13,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 现在请大家考虑三个问题: 对于公有派生, 派生类的对象可不可以直接赋值给基类对象? 基类对象的引用可不可以

8、引用一个派生类对象? 基类对象的指针可不可以指向一个派生类对象?,14,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 三个问题的具体表述如下: class Parent ; class Child : public Parent ; Child c; Parent p = c; /? Parent /?,15,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 三个问题的答案都是肯定的。请大家看一下父类对象和子类对象的内存布局就明白为什么答案是肯定的了:,16,基类对象,子类对象,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的

9、声明和继承方式 当一个派生类的对象直接赋值给基类对象时,很明显地,不是所有子类对象的东西都赋给了父类对象,赋予的只是子类对象的一部分。这叫做子类对象的“切片(sliced)”。 需要注意的是,如果在三个问题中将父类和子类的位置反过来,那么问题的答案就是全否。请大家自行思考问什么。,17,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 2. 私有派生 如果 为 private(或缺省),那么: 基类的保护成员在私有派生类中是私有成员; 基类的公有成员在私有派生类中是私有成员; 基类的私有成员和不可访问成员在私有派生类中成为派生类的不可访问成员。 也就是说,私有派生之后

10、,基类的成员就再也无法在以后的派生类中发挥作用,相当于阻止了基类功能的继续派生。(例6-5),18,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 3. 保护派生 C+语言还允许保护派生方式。保护派生方式下,基类的所有公有段成员和保护段成员都成为保护派生类保护段的成员;基类的私有成员和不可访问成员在保护派生类中成为派生类的不可访问成员。 保护派生方式一般很少使用。,19,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式,20,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 4.静态成员的派生 static成员受段

11、约束符的限制,基类和派生类共享基类的static成员。要求访问静态成员时,必须用“类名:成员”显式地说明。(例6-7),21,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 5.访问声明 类 D 从基类B私有派生,因而类D的派生类E不能访问间接基类 B 的所有成员,这种方法表达比较简洁。但有些时侯,这种”一刀切”的方法会带来问题。若希望类B的某几个成员还能被类E访问,而不是像现在这样全部变成类D的私有成员,让类E根本看不到。为了满足这种需要,C+提供了一种调节机制,称为访问声明,它使得 B 的某几个成员能被类 E 所访问。,22,第六章 继承和派生,6.1派生类的概

12、念 6.1.2 派生类的声明和继承方式 访问声明的形式为: (1)基类类名:基类保护段或公有段数据成员; (2)基类类名:基类保护段或公有段成员函数名;,23,class B int a;public:int b;void f(); ;,class D : private B int d;public:B:b;B:f;int c; ;,第六章 继承和派生,6.1派生类的概念 6.1.2 派生类的声明和继承方式 对访问声明的使用需要注意以下几点: (1)访问声明不能说明任何类型。 (2)访问声明仅用于派生类中恢复名字的访问权限,不允许在派生类中降低或提升基类成员的可访问性。 (3)对重载函数名的

13、访问声明将调整基类中具有该名的所有函数的访问域。,24,第六章 继承和派生,6.1派生类的概念 6.1.3基类对象的初始化 1.类等级 下面是一个继承链中的类等级图示:,25,要在派生类中访问与派生类同名的基类成员,采用 类名:成员 的方式。(例6-12),第六章 继承和派生,6.1派生类的概念 6.1.3基类对象的初始化 2. 基类对象的初始化 在 C+ 中,派生类构造函数的声明为: 派生类构造函数(变元表):基类(变元表),对象成员1(变元表),对象成员n(变元表) ; 构造函数执行时仍遵循先兄长(基类),再客人(对象成员),后自己(派生类)的顺序。另一方面,执行析构函数时,先执行派生类的

14、析构函数,再执行基类的析构函数。(例6-13-16),26,第六章 继承和派生,6.2多继承 6.2.1多继承的概念 至今所看到的例子中,派生类仅有一个直接基类,这称为单继承。但是一些类却代表两个或多个类的合成。例如,两用沙发,它是一个沙发,也是一张床,两用沙发应允许同时继承沙发和床的特征,即SleepSofa继承Bed和Sofa两个类,因此多继承是指一个派生类有两个或者两个以上的直接基类。(例6-17),27,第六章 继承和派生,6.2多继承 6.2.1多继承的概念,28,第六章 继承和派生,6.2多继承 6.2.2虚基类 1.虚基类的概念 在 C+ 中,一个类不能被多次说明为一个派生类的直

15、接基类,但可以不止一次地成为间接基类。这就导致了一些问题。为了方便说明,先介绍多继承的“类格”表示法。 派生类及其基类可用一有向无环图( DAG )表示,其中的箭头表示“由派生而来”。类的 DAG 图常称为一个“类格”。,29,第六章 继承和派生,6.2多继承 6.2.2虚基类 class L public:int next; ; class A : public L ; class B : public L ;,30,class C : public A, public B public:void f() next = 0; ;,第六章 继承和派生,6.2多继承 6.2.2虚基类,31,第六

16、章 继承和派生,6.2多继承 6.2.2虚基类 当在多条继承路径上有一个公共的基类(如本例的 L ),在这些路径中的某几条路径汇合处(如本例中的 C ),这个公共基类就会产生多个实例。也就是说,如果L中有一个叫做next的成员,那么在C中就有两个叫做next的成员。那么,下面的代码在编译时就会引起二义性错误: C Obj; Obj.next = 0; 而这条使正确的:Obj.A:next = 0;,32,第六章 继承和派生,6.2多继承 6.2.2虚基类 如果只想保存这个基类的一个实例,可以将这个公共基类说明为虚拟基类或称虚基类。它仅是简单地将关键字virtual加到基类的描述上,例如改写上述例子为: class A : virtual public L ; class B : virtual public L ;,33,B,第六章 继承和派生,6.2多继承 6.2.2虚基类 多继承优势会将问题变复杂。所以在现代的面向对象语言,比如Java中,就取消了多继承的概念。,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号