继承:减少重复代码
1、基本语法
class 子类 : 继承方式 父类
继承:减少重复代码
常规写法:将全部需要输出的内容写出来
继承实现页面:
- 将公共的代码抽离出来归为一个类
- 需要输出公共代码的类继承公共代码
案例
普通实现:写许多重复代码
继承实现:将公共的部分抽离出来作为一个BasePage类
再将不同的部分分别写为各个类,并且继承公共的部分
总结:
继承的好处:可以减少重复代码
class A :public B;
A类称为 子类 或 派生类
B类称为 父类 或 基类
public 为继承方式
派生类(子类)中的成员包含两大部分:
- 一类是从基类继承过来的(表现其共性)
- 一类是自己增加的成员(表现其个性)
2、继承方式
三种继承方式:
- 公共继承
- 保护继承
- 私有继承
三种继承方式的特点:
- 父类中私有属性无论哪种方式子类都访问不了
- 公共继承:父类中该属性是什么访问权限继承后还是什么访问权限(公共继承不改变属性的访问权限)
- 保护继承:能访问的父类属性继承后到子类中均变为保护权限(保护权限类内可以访问,类外不能访问,但是其子类可以访问)
- 私有权限:能访问到的父类属性继承后到子类中均变为私有权限(私有权限类内可以访问,类外不能访问,但是其子类不能访问)
注意:分清不同情况下哪一个类是子类
3、继承中的对象类型
问题:
从父类继承过来的成员,哪些属于子类对象中
测试方式:
用sizeof输出这个子类的内存大小,大小为16字节,说明子类从父类中继承了所有成员,只是父类中的私有属性(只是被编译器隐藏了)
结论
- 父类中所有非静态成员属性都会被子类继承下去
- 父类中私有成员属性是被编译器隐藏了,因此是访问不到,但确实是被继承下去了
利用开发人员命令提示工具查看对象模型:
- 从开始页面找到编译器的开发人员命令提示工具
- 跳转盘符:F:(cpp的盘符)
- 跳转文件具体路径:cd 具体路径下
- 查看命令(查看单个布局):cl /d1 reportSingleClassLayout类名 文件名
(文件名:类所在的文件)
4、继承中构造和析构顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:
父类和子类的构造和构析顺序是谁先谁后?
结论:
- 创建子类对象之前自动创建父类对象
- 先构造父类,再构造子类
- 先析构子类,再析构父类
5、继承同名成员处理方式
问题:
当子类与父类出现同名成员,如何通过子类对象访问到子类或者父类中的数据
呢?
处理方式:
同名成员属性:
- 子类对象访问子类同名成员,直接访问即可
- 子类对象访问父类同名成员,需要加作用域
同名成员函数:
- 直接调用 调用的则是子类中的同名成员函数
- 加上作用域 调用的则是父类的同名成员函数
- 如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中的所有同名成员函数(包括有参和无参),如果想访问到父类中被隐藏的同名成员函数,需要加作用域
完整测试代码:
6、继承同名静态成员处理方式
问题:
继承中同名静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致
- 访问子类同名成员 直接访问即可
- 访问父类同名成员 需要加作用域
继承中同名静态成员的两种访问方式
- 通过对象访问
- 通过类名访问
同名静态成员变量
注意:通过类名访问父类静态成员变量第一个::代表通过类名访问,第二个::代表访问父类作用域下
同名静态成员函数
7、多继承语法
C++允许一个类继承多个类
语法:
class 子类 ; 继承方式 父类1,继承方式 父类2.....
问题:
多继承可能会引发父类中有同名成员出现(如在多个继承的父类中都出现成员A),需要加分作用域
实际开发中不建议用多继承
当父类中出现同名成员,需要加作用域区分
8、菱形继承
有两个类,它们有共同的父类,也有共同的子类
概念:
- 两个派生类继承同一个基类
- 又有某个类同时继承两个派生类
这种继承被称为菱形继承,或者钻石继承
问题:
产生二义性
最小子类中会有两份最大基类中的数据
需要加以作用域区分
利用虚继承解决菱形继承问题
继承之前加上关键字 virtual 变为虚继承
虚基类:虚继承后最大的类称为虚基类
虚继承之后只有一份数据,所以可以不用加作用域区分
虚继承的底层
- 点击开始键,找到编译器文件下的开发人员命令提示符
- 跳转到文件所在盘符,cd到文件所在目录
- 输入命令dir,查看文件
- 输入命令cl /d1 reportSingleClassLayoutSheepTuo "08 菱形继承"
左图为虚拟继承后,右图为虚拟继承前,可以发现只继承了一份m_Age
而从Sheep和Tuo继承到的是vbptr
vbptr(虚基类指针)
vbptr指向vbtable(虚基类表),表内记录了指针和数据的偏移量,加上偏移量后可以通过指针找到唯一的数据