继承与派生是同一过程从不同角度的描述:
- 保持已有类的特性而构造新类的过程称为继承。
- 在已有类的基础上新增自己的特性而产生新类的过程称为派生。
被继承的已有类称为基类(或父类)。
派生出的新类称为派生类(或子类)。
直接参与派生出某类的基类称为直接基类。
基类的基类甚至更高层的基类称为间接基类。
继承的目的:实现设计与代码的重用。
派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要多原有程序进行改造。
单继承时派生类的定义:
class 派生类名:继承方式 基类名
{
成员声明;
}
//例子
class Derived:public Base
{
public:
Derived();
~Derived();
}
多继承时派生类的定义:
!!!每一个“继承方式”,只用于限制对紧随其后的基类的继承
class 派生类名:继承方式1 基类名1, 继承方式2 基类名2,...
{
成员声明;
}
//例子
class Derived:public Base1, private Base2
{
public:
Derived();
~Derived();
}
派生类的构成:
- 吸收基类成员
- 默认情况下派生类包含了全部基类中除构造和析构函数之外的所有成员。
- 改造基类成员
- 如果派生类声明一个和某基类成员同名的新成员,派生的新成员就隐藏或覆盖了外层同名成员。
- 添加新的成员
不同继承方式的影响主要体现在:
- 派生类成员对基类成员的访问权限;
- 通过派生类对象对基类成员的访问权限
三种继承方式
- 公有继承(public)
- 继承的访问控制
- 基类的public和protected成员:访问属性在派生类保持不变;
- 基类的private成员:不可直接访问。
- 访问权限
- 派生类中的成员函数:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;
- 通过派生类的对象:只能访问public成员。
- 继承的访问控制
- 私有继承(private)
- 继承的访问控制
- 基类的public和protected成员:都以private身份出现在派生类中;
- 基类的private成员:不可直接访问。
- 访问权限
- 派生类的成员函数:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;
- 通过派生类的对象:不能直接访问从基类继承的任何成员。
- 继承的访问控制
- 保护继承(protected)
- 继承的访问控制
- 基类的public和protected成员:都以protected身份出现在派生类中;
- 基类的private成员:不可直接访问。
- 访问权限
- 派生类中的成员函数:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;
- 通过派生类的对象:不能直接访问从基类继承过来的任何成员。
- 继承的访问控制
protected成员的特点与作用
- 对建立其所在类对象的模块来说,它与private成员的性质相同。
- 对于其派生类来说,它与public成员的性质相同。
- 即实现了数据隐藏,又方便继承,实现代码重用。
类型转换
- 公有派生类对象可以被当作基类的对象使用,反之则不可。
- 派生类的对象可以隐含转换为基类对象;
- 派生类的对象可以初始化基类的引用;
- 派生类的指针可以隐含转化为基类的指针。
- 通过基类对象名、指针只能使用从基类继承的成员。
派生类的构造函数
- 默认情况下,基类的构造函数不被继承,派生类需要定义自己的构造函数。
- C++11规定:可用using语句继承基类构造函数,但只能初始化从基类继承的成员。语法形式:using B::B;
如果不继承基类的构造函数
- 派生类新增成员:派生类定义构造函数初始化;
- 继承来的成员:自动调用基类构造函数进行初始化;
- 派生类的构造函数需要给基类的构造函数传递参数。
单继承时构造函数的定义语法:
派生类名::派生类名(基类所需的形参, 本类成员所需的形参):
基类名(参数表),本类成员初始化列表
{
//其他初始化;}
多继承时构造函数的定义语法:
派生类::派生类名(参数表)
基类名1(基类1初始化参数表),
基类名2(基类2初始化参数表),
...
基类名n(基类n初始化参数表),
本类成员初始化列表
{
//其他初始化;
}
派生类与基类的构造函数
- 当基类有默认构造函数时
- 派生类构造函数可以不向基类构造函数传递参数。
- 构造派生类对象时,基类的默认构造函数将被调用。
- 如需执行基类中带参数的构造函数
- 派生类构造函数应为基类构造函数提供参数。
多继承且有对象成员时派生的构造函数定义语法:
派生类名:派生类名(形参表):
基类名1(参数),基类名2(参数),...,基类名n(参数),
本类成员(含对象成员) 初始化列表
{
//其他初始化
};
构造函数的执行顺序
- 调用基类构造函数。
- 顺序按照它们被继承时声明的顺序(从左向右)。
- 对初始化列表中的成员进行初始化。
- 顺序按照它们在类中定义的顺序。
- 对象成员初始化时自动调用其所属类的构造函数。(由初始化列表提供参数)
- 执行派生类的构造函数体中的内容。