919092-C++程序设计教程-第7章 继承与多态性

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
8
7.1.2 成员的继承及访问权限
派生类不能继承的包括: 构造函数 析构函数 用户定义的new运算符 用户定义的赋值运算符 友员关系
9
7.1.2 成员的继承及访问权限
类和对象访问规则
类中三种不同属性的成员: 1) private :仅可在类中直接访问 2) public:可在类中直接访问, 亦可通过类
派生类对象 可直接访问
g3
7.1.2 成员的继承及访问权限
派生类成员访问属性的调整
同名成员 访问声明
16
7.1.2 成员的继承及访问权限
同名成员
派生类中的成员名和基类中的成员名相同 ,基类中的就自动被忽略
成员名前加上基类名和作用域标识符“::” 访问声明
在子类中将一个或多个继承的成员恢复其 在基类中的访问权限
抽象类
• 抽象类包含未实现的函数,因此只能作其 它类的基类,不能实例化。
• 不能实例化,所以不能作为参数类型,函 数返回类型或显式类型转换的类型,但可 以声明抽象类的指针或引用。
• 类层次结构中包含未完全实现函数的类都 是抽象类。
• 抽象类中定义的普通函数,派生类对象可 以调用。
引发的问题:
➢ 派生类中对基类成员属性的改变 ➢ 在派生类中定义构造函数及其它成员函
数时,基类构造函数和成员函数的影响
7
7.1.2 成员的继承及访问权限
不同继承方式的影响主要体现在
➢ 派生类成员对基类成员的访问控制 ➢ 派生类对象对基类成员的访问控制
继承方式
➢公有继承 public ➢私有继承 private ➢保护继承 protected
18
7.1.4 多继承
基类与派生类的对应关系
单继承:派生类只从一个基类派生。 多继承:派生类从多个基类派生。 多重派生:由一个基类派生出多个不
同的派生类。 多层派生:派生类又作为基类,继续
派生新的类。
19
7.1.4 多继承
多重继承的声明方式
class 派生类名:继承方式1 基类名1, 继承方式2 基类名2,...
基类中public 和 protected 成员在派 生类中具有private属性。 保护派生 (protected)
基类中public 和 protected 成员在派 生类中具有protected 属性。
14
7.1.2 成员
Class Base 私有:s
的继承及访 保护: b
问权限
公有: g 可直接访问
就是前面所介绍过的动态联编。
30
7.3.3 虚函数的定义及用法
定义: 在某基类中声明为 virtual,并在派生类中重新
定义的函数。(注意和虚基类区分) 形式:
virtual type fun_name(<arg_list>); 特点:
具有继承性。基类中定义了虚函数,派生类中无 论是否说明,同原型函数都自动为虚函数。
• 析构函数的执行顺序正好与上述顺序相反
21
7.1.5 基类对象与派生类对象的赋值关系
赋值兼容规则
在需要基类对象的任何地方都可以使用公 有派生类的对象来替代,替代有三种: 公有派生类对象可直接赋值给基类的对象,即
把派生类对象中从基类继承来的成员,逐个赋 值给基类对象的成员;反之,基类对象则不可 以赋给派生类对象。 公有派生类对象的地址可赋给基类指针变量。 公有派生类对象可以初始化基类引用。
用法: 在派生类中重新使用的基类名称::成员
名称;
17来自百度文库
7.1.3 基类成员的初始化
执行顺序
✓ 基类构造函数-派生类构造函数-派生类析构函数 -基类析构函数
构造规则:基类->对象成员->派生类
➢ 当基类构造函数有参数时,派生类必须有构造函数 ➢ 每个派生类负责其直接基类的的构造 ➢ 析构函数是独立的
23
7.2.1 派生关系中的二义性问题
class A { public:
int a; void f(); //... }; class B { public: int a;
24
void f(); //...
}; class C:public A,public B { //... }; 二义性错误: C cobject; cobject.a=10; //出错,具有二义性 cobject.f(); //出错,具有二义性
31
7.3.3 虚函数的定义及用法
•本质: 不是重载定义而是覆盖定义。被覆盖的成
员函数一般由作用域修饰符::指明调用
•调用方式: 通过基类指针或引用,执行时会根据指针
指向的对象的类,决定调用哪个函数。
•实现机制 编译系统采用动态联编方式来实现。
32
7.3.3 虚函数的定义及用法
实现动态联编需要的条件
继承的目的:实现代码重用。
派生的目的:当新的问题出现,原有程序无法解决 (或不能完全解决)时,需要对原有程序进行改造 。5
7.1.1 派生类的定义
派生类的定义方法
class <派生类名>:<继承方式><基类名> { <派生类新定义成员>
};
7.1.2 成员的继承及访问权限
派生(Derive):以基类的定义为基础 ,以公有、私有或保护方式继承基类的 全部成员(数据成员和成员函数),另外 根据需要声明派生类的成员。
在对源程序进行编译时确定消息与哪个方法 相联系。如:函数名重载,运算符重载。
动态联编 —— 运行时多态性
在程序运行时确定将要消息与哪个方法相联 系。如:继承,虚函数。
29
7.3.2 虚函数及其应用
虚函数是面向对象编程实现多态的基本 手段。
从父类中继承的时候,虚函数和被继承 的函数要求具有相同的签名。在运行过 程中,运行系统将根据不同的对象类型 ,自动地选择所匹配的运行方式。
C++实用教程
第七章 继承与多态性
章韵等
高等教育出版社
第7章 继承与多态性
7.1 类的继承与派生 7.2 虚基类 7.3 虚函数与多态性 7.4 程序设计举例
7.1 类的继承与派生
派生的基本概念
基类1
基类2
……
……
派生类
基类n
7.1 类的继承与派生
派生与继承的实例
交 通工具
汽车
小汽车
卡车
旅行车
的对象在类外访问 对象名.成员名
3) protected: 双重性
10
派生类中:public属性 在派生类中可直接访问
其他外部: private属性
7.1.2 成员的继承及访问权限
公有继承(public)
class 派生类名:public 基类名 {
成员定义; }
基类的public和protected成员的访问属性在派生 类中保持不变,但基类的private成员不可访问。
(1) 必须把动态联编的行为定义为类的虚函 数。 (2) 类之间存在子类型关系,一般表现为一 个类从另一个类公有派生而来。 (3) 必须先使用基类指针指向子类型的对象, 然后直接或者间接使用基类指针调用虚函数。
33
7.3.3 虚函数的定义及用法
使用虚函数需注意的问题
• 在类体系中访问虚函数,应使用指向基类类型的 指针或对基类类型的引用。
34
7.3.4 纯虚函数与抽象基类
定义:在基类中声明为虚函数,该基类 中不定义函数体。只声明,不实现。形 式: virtual 类型 函数名(参数表)=0
作用:对于暂时无法实现的函数,可以 声明为纯虚函数,派生类根据实际需要 定义自己的函数体。在基类中只定义其 名称和参数,可以统一实现。
35
7.3.4 纯虚函数与抽象类
工具车
轿车
面包车
4
7.1 类的继承与派生
类的继承与派生的基本概念
所谓继承就是从父辈处得到属性和行为特征。类的 继承,是新的类从已有类那里得到已有的特征。从 另一个角度看,从已有类产生新类的过程就是类的 派生。
被继承的已有类称为基类(或父类)。 派生出的新类称为派生类。派生类同样也可以作为
基类派生新的类,这样形成类的层次结构。
定义
–以virtual修饰说明基类 例:class B1:virtual public B
作用
–主要用来解决多继承时可能发生的对同一基类 继承多次而产生的二义性问题.
–为最远的派生类提供唯一的基类成员,而不重 复产生多次拷贝
注意:
–在第一级继承时就要将共同基类设计为虚基类 27 。
7.3 虚函数与多态性
派生类中的成员函数可以直接访问基类中的 public和protected成员,但不能访问基类的 private成员。
通过派生类的对象只能访问基类的public成员。
11
7.1.2 成员的继承及访问权限
私有继承(private)
class 派生类名:private 基类名 {
成员定义; }
基类的public和protected成员以private身份出 现在派生类中,但基类的private成员不可访问。
{ 成员定义;
} 注意:每一个“继承方式”,只用于限制对紧
随其后之基类的继承。对于不指定继承方式的 ,系统默认为:private。
20
7.1.4 多继承
多重继承的构造函数和析构函数
• 其次序和单继承下的相同:基类的构造函 数->对象成员的构造函数->派生类的构造 函数
• 相同层次的各基类之间取决于在派生类中 声明时从左到右的顺序
22
7.2 虚基类
7.2.1 派生关系中的二义性问题
在多继承时,基类与派生类之间,或 基类之间出现同名成员时,将出现访问 时的二义性(不确定性)—— 采用虚 函数或支配(同名覆盖)原则来解决。
当派生类从多个基类派生,而这些基 类又从同一个基类派生,则在访问此共 同基类中的成员时,将产生二义性—— 采用虚基类来解决。
s, b, g
Object abase 可直接访问
g
Class 保护继承同 私有继承
派生类对象 可直接访问
g, g2
15
Class 公有派生 私有:s2 保护: b2 公有: g2 可直接访问
b, g s2, b2, g2
Class 私有派生 私有: s3 保护: b3 公有: g3 可直接访问
b, g, s3,b3,g3
C cobject; cobject.a=10; cobject.f(); cobject.A::a=10; c2o6 bject.B::f();
//使用C::a //调用C::f(); //使用A::a //调用B::f();
7.2.2 虚基类的应用
虚基类的引入
–用于在继承时有共同基类的场合
派生类中的成员函数可以直接访问基类中的 public和protected成员,但不能访问基类的 private成员。
通过派生类的对象不能访问基类中的任何成员。
12
7.1.2 成员的继承及访问权限
保护继承(protected)
class 派生类名:protected 基类名 {
成员定义; }
基类的public和protected成员都以protected身 份出现在派生类中,但基类的private成员不可访 问。
base *p; p=&b;
• 派生类中重新定义虚函数,该函数的返回值、参 数个数、类型与基类中声明完全一致;且不能出 现同样原型的非虚函数。
• 虚拟属性具有继承性。若派生类中没有重新定义 虚函数,该类的对象将使用基类中虚函数代码。
• 虚函数必须是一个类的成员函数,不可是友员、 构造或静态函数。
• 可以将析构函数定义成虚函数。
多态性是面向对象程序设计的重 要概念和机制,属于面向对象方 法的三大特性之一。
指的是发出同样的消息被不同类 型的对象接收时导致完全不同的 行为。
28
7.3.1 静态联编与动态联编
联编(binding):把函数名与其函数体的程 序代码连接在一起。更进一步,将符号与存 储地址联系在一起。
OOP中,把消息与方法联系在一起。 静态联编 —— 编译时多态性
派生类中的成员函数可以直接访问基类中的 public和protected成员,但不能访问基类的 private成员。
1通3 过派生类的对象不能访问基类中的任何成员。
7.1.2 成员的继承及访问权限
派生类的成员变化规则 公有派生(public)
基类中public 和 protected 成员在派 生类中保持原有的属性。 私有派生 (private)
7.2.1 派生关系中的二义性问题
二义性的解决方法
解决方法一:用类名来限定(确定名域) 派生类对象.基类名::方法名()
C cobject; cobject.A::a=10; //正确 cobject.B::f(); //正确
25
7.2.1 派生关系中的二义性问题
二义性的解决方法
解决方法二:同名覆盖 在派生类中再定义一个同名成员函数f() ,该函数再根据需要调用:某个基类::f()
相关文档
最新文档