第六章 继承和派生
6.1 继承和派生的基本概念
这种通过特殊化已有的类来建立新类的过程,叫做“类的派生”,原来的类叫做“基类”,新建立的类则叫做“派生类”。另一方面,从类的成员角度看,派生类自动地将基类的所有成员作为自己的成员,这叫做“继承”。基类和派生类又可以分别叫做“父类”和“子类”,有时也称为“一般类”和“特殊类”。
从一个或多个以前定义的类(基类)产生新类的过程称为派生,这个新类称为派生类。派生的新类同时也可以增加或者重新定义数据和操作,这就产生了类的层次性。
类的继承是指派生类继承基类的数据成员和成员函数。继承常用来表示类属关系,不能将继承理解为构成关系。
当从现有的类中派生出新类时,派生类可以有以下几种变化:
(1)增加新的成员(数据成员或成员函数)
(2)重新定义已有的成员函数
(3)改变基类成员的访问权限
C++派生类使用两种基本的面向对象技术:第一种称为性质约束,即对基类的性质加以限制;第二种称为性质扩展,即增加派生类的性质。
C++中有两种继承:单一继承和多重继承。对于单一继承,派生类只能有一个基类;对于多重继承,派生类可以有多个基类。
6.2 单一继承
6.2.1 单一继承的一般形式
在C++,声明单一继承的一般形式如下:
class 派生类名:访问控制 基类名{
private:
成员声明列表
protected:
成员声明列表
public:
成员声明列表
};
这里和一般的类声明一样,用关键字class声明一个新的类。冒号后面的部分指示这个新类是哪个基类的派生类。所谓“访问控制”是指如何控制基类成员在派生类中的访问属性。它是3个关键字public、private、protected中的一个。一对大括号“{}”是用来声明派生类自己的成员的。
6.2.2 派生类的构造函数和析构函数
定义派生类的构造函数的一般形式如下:
派生类名::派生类名(参数表0) : 基类名(参数表)
{...//函数体}
冒号后“基类名(参数表)”称为成员初始化列表,参数表给出所调用的基类构造函数所需要的实参。实参的值可以来自“参数表0”,或由表达式给出。
构造函数(包括析构函数)是不被继承的,所以一个派生类只能调用它的直接基类的构造函数。当定义派生类的一个对象时,首先调用基类的构造函数,对基类成员进行初始化,然后执行派生类的构造函数,如果某个基类仍是一个派生类,则这个过程递归执行。该对象消失时,析构函数的执行顺序和执行构造函数的顺序正好相反。
6.2.3 类的保护成员
C++语言规定,使用公有方式产生的派生类成员函数可以直接访问基类中定义的或从另一个基类继承来的公有成员,但不能访问基类的私有成员。
在类的声明中,关键字protected之后声明的是类的保护成员。保护成员具有私有成员和公有成员的双重角色;对派生类的成员函数而言,它是公有成员,可以被访问;而对其他函数而言则仍是私有成员,不能被访问。
6.2.4 访问权限和赋值兼容规则
1.公有派生和赋值兼容规则
在公有派生的情况下,基类成员的访问权限在派生类中保持不变。这就意味着:
(1)基类的公有成员在派生类中依然是公有的。
(2)基类的保护成员在派生类中依然是保护的。
(3)基类的不可访问的和私有的成员在派生类中也仍然时不可访问的。
当希望类的某些成员能够被派生类所访问,而又不能被其他的外界函数访问的时候,就应当把它们定义为保护的。
所谓赋值兼容规则是指在公有派生情况下,一个派生类的对象可以作为基类的对象来使用的情况。
注意:静态成员可以被继承,这时基类对象和派生类的对象共享该静态成员。
2.“isa”和“has-a”的区别
类与类之间的关系有两大类:一是继承和派生问题,二是一个类使用另一个类的问题。后者的简单用途是把另一个类的对象作为自己的数据成员或者成员函数的参数。
对于继承,首先要掌握公有继承的赋值兼容规则,理解公有继承“就是一个(isa)”的含义。
分层也可以叫做包含、嵌入或者聚合。公有继承的意思是“isa”。与此相反,分层的意思是指“has-a(有一个)”。
3.公有继承存取权限表
注意:静态成员可以被继承,这时,基类对象和派生类的对象共享该静态成员。
4.私有派生
通过私有派生,基类的私有和不可访问成员在派生类中是不可访问的,而公有和保护成员这时就成了派生类的私有成员,派生类的对象不能访问继承的基类成员,必须定义公有的成员函数作为接口。更重要的是,虽然派生类的成员函数可通过定义自定义的函数访问基类的成员,但将派生类作为基类在继续派生时,这时即使使用公有派生,原基类公有成员在新的派生类中也将是不可访问的。
5.保护派生
派生也可以使用protected。这种派生使原来的权限都降一级使用,即private变为不可访问;protected变为private;public变为protected。因为限制了数据成员和成员函数的访问权限,所以用的比较少。它与private继承的主要区别在于下一级的派生中。
6.3 多重继承
一个类从多个基类派生的一般形式如下:
class 类名1:访问控制 类名2,访问控制 类名3,...,访问控制 类名n
{...//定义派生类自己的成员};
6.4 二义性及其支配规则
对基类成员的访问必须是无二义性的,如使用一个表达式的含义能解释为可访问多个基类中的成员,则这种对基类成员的访问就是不确定的,称这种访问具有二义性。
6.4.1 作用域分辨符和成员名限定
从类中派生其他类可能导致几个类使用同一个成员函数名或数据成员名。程序必须确切地告诉编译器使用哪个版本的数据成员或成员函数。
如果基类中的名字在派生类中再次声明,则派生类中的名字隐藏了基类中的相应名字。C++可以迫使编译器“看到”当前作用域的外层部分,存取那些被隐藏的名字,这是由作用域分辨运算符“::”实现的(简称作用域运算符)。这一过程叫做作用域分辨。作用域分辨操作的一般形式如下:
类名::标识符
“类名”可以是任意基类或派生类名,“类标识符”是该类中声明的任一成员名。
6.4.2 派生类支配基类的同名函数
基类的成员和派生类新增的成员都具有类作用域,基类在外层,派生类在内层。如果这时派生类定义了一个和基类成员函数同名的新成员函数(因为参数不同属于重载,所以这里是指具有相同参数表的成员函数),派生类的新成员函数就覆盖了外层的同名成员函数。在这种情况下,直接使用成员函数名只能访问派生类的成员函数,只有使用作用域分辨,才能访问基类的同名成员函数。
派生类D中的名字N支配基类B中同名的名字N,称为名字支配规则。
分享到:
相关推荐
C++程序设计与数据结构基础:第6章 继承和派生类.ppt
【C语言程序设计第七章:继承与派生】 在面向对象编程中,继承与派生是两个核心概念,尤其在C++这样的多态性语言中,它们是构建复杂软件结构的关键。继承允许我们创建新的类(派生类),这些新类能够保留已有的类...
在C++中,继承与派生是面向对象编程的核心特性之一,它们允许创建新的类(派生类)基于已存在的类(基类),从而实现代码的重用和类的层次结构。这一章节主要讲解了以下几个方面的知识: 1. **继承(Inheritance)*...
在实验内容的第一部分,我们看到`Person`类作为基类,派生出`Student`和`Teacher`两个类,这体现了单继承的概念。`Student`类增加了关于成绩的数据成员和相应的成员函数,`Teacher`类则添加了教学相关的数据成员。 ...
从bicycle和motorcar派生出motorcycle,观察虚基类对继承的影响。 定义一个motorcycle的对象,分别调用run()和stop(),观察构造/析构函数的调用情况。 注意:构造函数和析构函数中均为cout语句,说明哪个构造/析构...
6. 多继承与虚基类,多继承可能导致基类成员在派生类中存在多个副本,虚基类的作用是在多继承中解决二义性问题,确保共享基类只有一份实例。 7. 子类型关系,指的是派生类和基类之间的关系,派生类可以被视为基类的...
在第六页中,作者介绍了基类成员在派生类中的访问权限,包括公有继承、私有继承和保护继承的访问权限。公有继承方式下,基类成员在派生类中不变;私有继承方式下,基类成员在派生类中为私有的;保护继承方式下,基类...
4. 继承与派生:继承是面向对象的一个关键特性,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和行为。通过继承,子类可以扩展或修改父类的功能,实现代码的复用和类层次结构的建立。 5. 多态性与...
### Unity基础 C# 第六章 继承与多态 #### 一、继承的基本概念 在面向对象编程中,继承是一种强大的工具,它允许我们基于现有的类定义新的类。这不仅可以减少代码重复,还能使代码结构更加清晰。通过继承,子类会...
继承是面向对象编程的一个特性,它允许一个类(称为子类或派生类)继承另一个类(称为父类、基类或超类)的属性和方法。在这个例子中,`Rectangle`、`Circle` 和 `Square` 都是从 `Shape` 类继承的。这使得子类能够...
本课件“C++课件第九章继承共29页”深入探讨了这一主题,旨在帮助学习者掌握这一强大的工具。以下是关于C++继承的详尽解析: 1. 继承的概念: 继承是OOP(面向对象编程)的关键特性,它允许一个类(子类或派生类)...
通过上述示例和分析,我们可以看到继承与派生在C++程序设计中的应用,如何通过继承方式来控制访问权限,以及如何在派生类中访问基类的成员变量和成员函数。掌握这些概念对于深入理解面向对象编程是至关重要的。
公有继承(public inheritance)意味着基类的公有和保护成员在派生类中也是公有和保护的,但私有成员不可见。在实验中,`person`类的成员在`student`和`teacher`类中都是可访问的,这样就可以方便地处理学生和教师的...
第一部分 面向过程的程序设计 第1章 C++概述 第2章 数据类型、运算符和表达式 第3章 简单的输入/输出 第4章 C++的流程控制 第5章 函数 ...第12章 继承和派生 第13章 多态性 第14章 输入/输出流 第15章 模板
第一章 C++概述,第二章 数据类型、运算符与表达式,第三章 简单的输入输出,第四章 C++的流程控制语句,第五章 函数与编译预处理,第六章 数组 ,第七章 结构体、共同体和枚举类型 ,第八章 指针和引用,第九章 类...
绪论 第9章 运算符重载 第2章 数据类型和表达式 第10章 静态成员与友元 第3章 控制语句 第11章 继承和派生类 第4章 函数 第12章 模板 第5章 数组 第13章 多态性与虚函数 第6章 指针 第14章 I/0...
第6章 指针 第7章 自定义数据类型 第8章 类和对象 第9章 关于类和对象的进一步讨论 第10章 运算符重载 第4篇 面向对象的程序设计 第11章 继承与派生 第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具
第6章 指针 第7章 自定义数据类型 第8章 类和对象 第9章 关于类和对象的进一步讨论 第10章 运算符重载 第4篇 面向对象的程序设计 第11章 继承与派生 第12章 多态性与虚函数 第13章 输入输出流 第14章 C++...
第6章 指针 第7章 自定义数据类型 第第3篇 基于对象的程序设计 第8章 类和对象 第9章 关于类和对象的进一步讨论 第10章 运算符重载 第4篇 面向对象的程序设计 第11章 继承与派生 第12章 多态性与虚函数 第13章 输入...