继承
8.1类之间都关系
在面向对象技术中,类是数据和操作的集合,它们之间有3种主要的关系:has-a,uses-a和is-a.
l Has-a表示类的包含关系,用于描述一个类由多个“部件类”构成。
l Use-a表示一个类部分的使用另一个类。
l Is-a表示一种分类方式,描述类的抽象和层次关系
Ø Is-a关系具有传递性,is-a机制称为“继承”。
Ø 派生类构造函数以参数初始式调用基类构造函数。
8.2基类和派生类
C++中描述类继承关系的语句格式为:
Class 派生类 :基类名表
{ 数据成员和成员函数说明};
其中“基类名表”的格式如下:
访问控制 基类名1,访问控制 基类名2 ……
用于表示当前定义的派生类的各个基类。
“访问控制”表示继承权限的关键字,称为访问描述符。
l Public 公有继承
l Private 私有继承
l Protected 保护继承
如果省略访问描述符,则c++认为是私有继承。
派生类不同的继承方式对基类成员有不同的访问权限。
一个派生类的的成员有两部分组成,一部分从基类继承过来,;另一部分自己定义,即创建一个派生类的对象时,系统会建立所有继承和自身定义的成员。但派生类不一定能直接使用(可见)这些成员。派生类对基类成员的使用,除了与类定义的继承访问控制有关外,还与基类中成员的性质有关。
一个派生类公有继承一个基类时,基类中所有公有成员(由public定义的数据成员或成员函数)成为派生类的公有成员,基类中所有保护乘员成为派生类的保护成员。
一个派生类私有继承一个基类时基类中所有公有成员和保护成员成为派生类私有成员。
不论派生类以何种方式继承基类,都不能直接使用基类的私有成员。
1. 公有继承
以公有方式继承的派生类,基类的public和protected成员在派生类中的性质不变。即派生类中可以使用基类中定义的public和protected成员;并且,基类的公有成员也是派生类对象的接口,可以在类模板之外被访问。
派生类包含类多的可以赋值给包含类少的,反之不行。
2. 私有继承
以私有方式继承的派生类,基类的public和protected成员会成为派生类的私有成员,即基类中定义的public和protected成员只能在私有继承的派生类中可见,而不能在类外使用。
3. 保护继承
保护继承把基类的公有成员和保护成员作为派生类的保护成员,使其在派生类中被屏蔽。
保护继承和私有继承方式在程序设计中应用较少。原因是,继承的目的是软件重用,如果有需要屏蔽的成员,通常在类中被定义为私有的或保护的成员。
4. 访问声明
C+提供一种访问调节机制,使一些本来在派生类中不可见的成员变为可访问的,称为访问声明。
注意事项:
(1) 访问声明仅调整名字的访问权限
(2) 访问声明不允许在派生类中降低或提升基类成员的可访问性
(3) 对重载函数名的访问声明将调整基类所有同名函数的访问域。
派生类的继承过程:
l 吸收基类成员(全部吸收(构造、析构除外),但不一定可见)
l 改造基类成员
l 添加派生类新成员
8.2.2重名成员
C++允许派生类的成员与基类成员重名。在派生类中访问重名成员时,屏蔽基类的同名成员。如果在派生类中使用基类的同名成员,可以显示的使用作用域符指定,格式如下:
类名::成员
1. 重名数据成员
如果在派生类中定义了与基类相同的数据成员,根据继承规则,在建立派生类对象时系统会分别建立不同的储存空间。
2. 重名成员函数
在派生类中定义与基类同名的数据成员函数,称为在派生类重载基类的成员函数。由调用形式指示this指针的不同类型,调用不同版本的成员函数。
3. 关于类成员的作用域和可见性
8.2.3派生类中访问静态成员
如果在基类中定义了静态成员,这些静态成员将在整个类体系中被共享,根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具有不同的访问性质。
8.3基类的初始化
构造函数名(变元表):基类(变元表),数据成员(变元表)……
它同样可以用于调用基类构造函数。冒号“:”后面是基类构造函数及对象成员各自对应的参数初始式。构
造函数的执行顺序是:首先执行基类,然后执行类对象成员,最后执行派生类本身。如如果有间接基类,则首先执行间接基类构造函数。它们的执行顺序是由系统规定的,与参数初始式列表安排无关。参数初始式列表的任务只是传递参数。例如,用户可以把基类初始化“基类(变元表)”放在最后,系统依然首先执行基类的构造函数,完成派生数据成员的初始化。
程序先执行基类构造函数,再执行派生类的构造函数。因为派生类对象的创建以基类为先心决条件,.所以,初始化时首先执行基类构造函数。而执行析构函数的顺序相反,首先析构派生类对象,然后析构基类对象。
派生类构造函数以参数初始式调用基类构造函数。
派生类构造函数和析构函数的定义规则:
- 基类的构造函数和析构函数不能被继承
- 如果基类没有定义构造函数或有无参的构造函数, 派生类也可以不用定义构造函数
- 如果基类无无参的构造函数,派生类必须定义构造函数
- 如果派生类的基类也是派生类,则每个派生类只负责直接基类的构造
派生类是否定义析构函数与所属的基类无关
派生类的构造函数的定义:
l 派生类的数据成员既包括基类的数据成员,也包括派生类新增数据成员。
l 在C++中,派生类构造函数的一般格式为:
派生类::派生类名(参数总表):基类名(参数表)
{
// 派生类新增成员的初始化语句
}
注意:这是基类有构造函数且含有参数时使用
派生类析构函数
1)当派生类中不含对象成员时
●在创建派生类对象时,构造函数的执行顺序是:基类的构造函数→派生类的构造函数;
●在撤消派生类对象时,析构函数的执行顺序是:派生类的析构函数→基类的析构函数。
(2)当派生类中含有对象成员时
●在定义派生类对象时,构造函数的执行顺序:基类的构造函数→对象成员的构造函数→派生类的构造函数;
●在撤消派生类对象时,析构函数的执行顺序:派生类的析构函数→对象成员的析构函数→基类的析构函数