版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
继承和派生
一. 继承和派生的概念
1. 继承和派生
继承,就是从先辈处得到属性和行为的特征。类的继承就是新的类从已有的类那里得到已有的特性。从另一个角度来看问题,从已有类产生新类的过程就是类的派生。
基类和派生类的关系,可以表述为:派生类是基类的具体化,而基类是派生类的抽象。
2. 派生类的声明
格式为:
class 派生类名:[继承方式] 基类
{
派生类新增的数据成员和成员函数
};
“基类名”是一个已经声明的类的名称,“派生类名”是继承原有类的特性而生成的新类的名称。“继承方式”规定了如何访问从基类中继承的成员,他可以是关键字:private, protected, public,分别表示私有继承,保护继承和共有继承,默认为私有继承。
3. 基类成员在派生类中的访问属性
- 基类中的私有成员。无论哪种继承方式,基类中的私有成员不允许派生类继承,即在派生类中不可直接访问。
- 基类中的共有成员:
公有继承时,基类中的所有公有成员在派生类中仍以公有成员的身份出现。
私有继承时,基类中的所有公有成员在派生类中仍以私有成员的身份出现。
保护继承时,基类中的所有公有成员在派生类中仍以保护成员的身份出现。 - 基类中的保护成员:
公有继承时,基类中的所有保护成员在派生类中仍以保护成员的身份出现。
私有继承时,基类中的所有保护成员在派生类中都是以私有成员的身份出现。
公有继承时,基类中的所有保护成员在派生类中仍以保护成员的身份出现。
4. 派生类对基类成员的访问规则
- 私有继承的访问规则
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
访问方式(内部访问) | 不可访问 | 可访问 | 可访问 |
访问方式 (对象访问) | 不可访问 | 不可访问 | 不可访问 |
- 公有继承的访问规则
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
访问方式(内部访问) | 不可访问 | 可访问 | 可访问 |
访问方式 (对象访问) | 不可访问 | 可访问 | 不可访问 |
- 保护继承的访问规则
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
访问方式(内部访问) | 不可访问 | 可访问 | 可访问 |
访问方式 (对象访问) | 不可访问 | 不可访问 | 不可访问 |
二. 派生类的构造函数和析构函数
构造函数的主要作用是对数据进行初始化。但是基类的构造函数和析构函数不能被继承,因此我们必须在派生类的构造函数中对基类的构造函数所需要的参数进行设置。
1. 派生类构造函数和析构函数的调用顺序
构造函数的调用严格地按照先调用基类的构造函数,后调用派生类的对象进行,析构函数的调用顺序于构造函数的调用顺序正好相反,先调用派生类的析构函数,再调用基类的构造函数。
2. 派生类构造函数和析构函数的构造规则
派生类的构造函数的一般规则:
派生类名(参数总表): 基类名(参数表)
{
派生类新增的数据成员的初始化语句
}
【例 1】
#include<iostream>
using namespace std;
class B
{
int i;
public:
B(int i_)
{
i = i_;
cout << "c base" << endl;
}
~B(){ cout << "d base" << endl; }
int show_B(){ cout << i << endl; }
};
class D:public B
{
int j;
public:
D(int i_, int j_):B(i_)
{
j = j_;
cout << "c derived" << endl;
}
~D(){ cout << "d derived" << endl; }
int show_D(){ cout << j << endl; show_B(); }
};
int main()
{
D obj(50, 60);
obj.show_D();
return 0;
}
结果如下:
c base
c derived
60
50
d derived
d base
2. 含有子对象的派生类的构造函数
一般形式:
派生类名(参数总表):基类名(参数表0),子对象名1(参数表1),....,子对象名n(参数表n)
{
派生类新增成员的初始化语句
}
构造函数的调用顺序:
- 调用基类的构造函数,对基类数据成员初始化
- 调用子对象的构造函数,对子对象的数据成员初始化
- 调用派生类的够着函数提,对派生类数据成员初始化
撤销对象的时候,析构函数的调用顺序与构造函数的调用顺序刚好相反。首先调用派生类的析构函数,在调用子对象的析构函数,最后调用基类的析构函数。