一、继承的基本概念
1、概念
在 C++ 中,继承是一种面向对象编程(OOP)的重要机制,它允许一个类(派生类或子类)继承另一个类(基类或父类)的属性和行为。通过继承,派生类可以复用基类的代码,并且可以在此基础上添加自己的新特性,从而实现代码的复用和扩展
代码示例:
#include <iostream>
// 基类(父类)
class Base {
public:
void show() {
std::cout << "基类(父类)" << std::endl;
}
};
// 派生类(子类)
class son : public Base {
public:
void display() {
std::cout << "派生类(子类)" << std::endl;
}
};
2、关于继承的称呼
一个类B 继承来自 类 A 我们一般称呼
A类:父类 基类
B类: 子类 派生类
B继承自A A 派生了B
3、意义
可以实现代码复用,减少重复代码的劳动量
继承是实现多态的必要条件
继承本身就是为了实现多态的,顺便实现了代码复用
我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。
这个时候我们就可以考虑利用继承的技术,减少重复代码
二、继承的基本语法
1、基本语法
class 子类名称:继承方式 父类名称
{
子类新增的成员;
}
class B:public A
{
}
2、基类对象初始化
// 在继承时,需要在子类的构造函数的初始化表中 显性的调用父类的构造函数 来完成对父类成员的初始化
格式
构造函数名(int val_1 , int val_2): class_A(val_1 , val_2);
3、派生类中调用基类
类外访问:
对象名.基类名::变量;
对象名.基类名::函数名(函数的实参表);
类内访问:
基类名::变量;
基类名::函数名(函数的实参表);
三、继承方式
1、公有继承
特点:
- 基类的公有成员在派生类中仍然是公有的,派生类对象可以在类外部直接访问这些成员。
- 基类的保护成员在派生类中仍然是保护的,只能在派生类及其派生类的成员函数内部访问,不能在类外部直接访问。
- 基类的私有成员在派生类中不可直接访问,只能通过基类的公有或保护成员函数间接访问。
2、私有继承
特点:
- 基类的公有成员和保护成员在派生类中都变成私有的,只能在派生类的成员函数内部访问,派生类对象在类外部不能直接访问。
- 基类的私有成员在派生类中不可直接访问,同样只能通过基类的公有或保护成员函数间接访问。
3、保护继承
特点:
- 基类的公有成员和保护成员在派生类中都变成保护的,只能在派生类及其派生类的成员函数内部访问,派生类对象在类外部不能直接访问。
- 基类的私有成员在派生类中不可直接访问,需要通过基类的公有或保护成员函数间接访问。
四、析构和构造
1、构造
1、父类的构造函数不会被子类继承
2、需要在子类的构造函数的初始列表中,显性的调用父类函数的构造函数
完成对父类中继承过来的成员初始化
3、如果没有在子类的构造函数初始化列表中调用父类中的构造函数 则使用无参构造
如果父类没有无参构造 会报错
4、构造函数的调用顺序是
先调用父类函数的构造函数
再调用子类函数的构造函数
2、析构
1、父类的析构函数不会被子类继承
2、不管是否显性调用父类的析构函数,父类的析构函数都会被调用
完成对父类中继承过来的成员的善后工作
3、子类的析构函数中 无需调用父类的析构函数
4、析构函数的调用顺序是
先调用子类函数的析构函数
再调用父类函数的析构函数
3、拷贝构造
1、如果子类中没有显性的定义拷贝构造函数,编译器会给子类提供一个默认的拷贝构造函数,而且默认提供的拷贝构造函数,会自动调用父类的拷贝构造函数,完成对从父类中继承过来的成员的初始化。
2、如果子类中显性的定义了拷贝构造函数,需要在子类的拷贝构造函数的初始化表中显性的调用父类的拷贝构造函数。
如果没有显性的调用父类的拷贝构造函数,默认会调用父类的无参构造函数来完成对从父类中继承过来的成员的初始化。
3、如果父类中没有指针成员,使用默认的拷贝构造函数
但是如果父类中有指针, 则需要考虑一下深浅拷贝的问题
五、多重继承
一个子类合一有多个直接父类共同派生,这种派生方式,叫做多重继承
子类会继承每个基类的成员
格式
构造函数的调用顺序 和 声明的顺序有关
class 子类名:继承方式 父类名 , 继承方式 父类名 .....
示例程序
联系
定义一个圆类(Circle):成员-->半径(radius)面积(area)及相关函数
定义一个桌子类(Desk):成员-->高度(high)材质(texture)及相关函数
由这两个类共同派生出圆桌类(Circle_dest):
新增成员颜色(color) 及相关函数
实例化一个圆桌类 输出相关对象