一、基础
- 继承:获得基类的全部特性;(基类的基类称为间接基类)
- 派生:继承基类后再增加一些特性而形成类。
二、语法
1. 单继承:只继承一个基类;
2. 多继承:继承多个基类。
⚠️默认情况下,构造函数和析构函数不被继承,而using
语句继承基类的构造函数(C++11)
3. 继承方式
(1)公有继承
- 基类
public
、protected
成员在派生类中的访问属性不变,而private
不可直接访问;
- 访问权限
- 派生类的成员函数:直接访问基类
public
、protected
成员,不能访问基类private
成员 - 派生类对象:其在类外,故只能访问
public
。
- 派生类的成员函数:直接访问基类
(2)私有继承:封堵基类的公有访问接口
- 基类的
public
、protected
成员在派生类的访问属性均定义为private
成员,而基类的private
成员不可直接访问;
- 访问权限
- 派生类的成员函数:直接访问基类
public
、protected
成员,不能访问基类private
成员 - 派生类对象:不能访问从基类继承的任何成员。
- 派生类的成员函数:直接访问基类
(3)保护继承
- 基类的
public
、protected
成员在派生类的访问属性均定义为protected
成员,而基类的private
成员不可直接访问;
- 访问权限
- 派生类的成员函数:直接访问基类
public
、protected
成员,不能访问基类private
成员 - 派生类对象:不能访问从基类继承的任何成员。
- 派生类的成员函数:直接访问基类
继承的访问控制对比表
基类public
|
基类protected
|
基类private
|
||
---|---|---|---|---|
⌘在派生类中的 访问属性 |
公有继承 | public |
protected |
❌ |
私有继承 | private |
private |
❌ | |
保护继承 | protected |
protected |
❌ | |
⌘访问权限 | —— | —— | —— | —— |
+ 派生类的成员函数 | 公有继承 | 直接访问 |
直接访问 |
❌ |
私有继承 | 直接访问 |
直接访问 |
❌ | |
保护继承 | 直接访问 |
直接访问 |
❌ | |
+ 派生类的对象 | 公有继承 | ✔️ | ❌` | ❌ |
私有继承 | ❌ | ❌ | ❌ | |
保护继承 | ❌ | ❌ | ❌ |
⚠️保护继承后,在类外,通过派生类的对象不能访问基类继承的成员,只能访问派生类新增的成员;派生类中的成员函数可以直接访问。既实现了数据隐藏,又方便继承,实现代码重用。
三、类型转换
- 公有派生类对象可被当基类的对象使用,基类不可当派生类;派生类对象可以隐含转换为基类对象、基类的指针,也可初始化基类引用。
- 转换后,通过基类对象名、指针只能使用从基类继承的成员,派生类中的新增成员就不能使用了。
四、派生类构造函数
1. 从基类继承:using B::B;
(1)只能初始化从基类继承过来的成员,新增成员就不能通过构造函数初始化;
(2)用于派生类新增很少或没有新增成员的派生类的初始化;
(3)新增成员只能通过类内初始值或默认初始值初始化;
2. 派生类构造函数
(1)单继承
class A{
public:
A();
A(int i):a(i){}
~A();
private:
int a;
};
class B : public A {
public:
B();
B(int i,int j):A(i),b(j){} // 派生类(单继承)构造函数
~B();
private:
int b;
};
(2)多继承
(3)多继承且有对象成员时,派生类构造函数定义
3. 派生类的复制构造函数
(1)派生类未定义复制构造函数时,由系统默认生成;
(2)派生类定义复制构造函数
- 一般都要为基类复制构造函数传递参数;
- 派生类复制构造函数只能接受一个参数
- 用来初始化派生类定义的成员
- 也将被传递给基类的复制构造函数;
4. 派生类的析构函数(不能从基类继承)
(1)声明方法与无继承关系时,类的析构函数相同;
(2)先执行派生类析构函数的函数体,再调用基类的析构函数。
五、虚基类virtual
为了解决“派生类从多个基类派生,而这些基类又有共同基类,则在访问此共同基类的成员时,将产生冗余,并有可能因冗余带来不一致性”的问题。⚠️在第一级继承时就要将共同基类设计为虚基类。