C++继承

本文详细介绍了C++中的继承原理,如何通过继承减少代码重复,以及各种继承方式(公共、保护、私有)、构造和析构顺序、同名成员处理、多继承和菱形继承的特性。还重点讲解了虚继承如何解决菱形继承带来的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承:减少重复代码

1、基本语法

class 子类 : 继承方式 父类

继承:减少重复代码

常规写法:将全部需要输出的内容写出来

继承实现页面:

  1. 将公共的代码抽离出来归为一个类
  2. 需要输出公共代码的类继承公共代码

案例

普通实现:写许多重复代码

继承实现:将公共的部分抽离出来作为一个BasePage类

再将不同的部分分别写为各个类,并且继承公共的部分

总结:

继承的好处:可以减少重复代码

class A :public B;

A类称为 子类 或 派生类

B类称为 父类 或 基类

public 为继承方式

派生类(子类)中的成员包含两大部分:

  1. 一类是从基类继承过来的(表现其共性)
  2. 一类是自己增加的成员(表现其个性)

2、继承方式

三种继承方式:

  • 公共继承
  • 保护继承
  • 私有继承

三种继承方式的特点:

  1. 父类中私有属性无论哪种方式子类都访问不了
  2. 公共继承:父类中该属性是什么访问权限继承后还是什么访问权限(公共继承不改变属性的访问权限)
  3. 保护继承:能访问的父类属性继承后到子类中均变为保护权限(保护权限类内可以访问,类外不能访问,但是其子类可以访问)
  4. 私有权限:能访问到的父类属性继承后到子类中均变为私有权限(私有权限类内可以访问,类外不能访问,但是其子类不能访问)

注意:分清不同情况下哪一个类是子类

3、继承中的对象类型

问题:

从父类继承过来的成员,哪些属于子类对象中

测试方式:

用sizeof输出这个子类的内存大小,大小为16字节,说明子类从父类中继承了所有成员,只是父类中的私有属性(只是被编译器隐藏了)

结论

  • 父类中所有非静态成员属性都会被子类继承下去
  • 父类中私有成员属性是被编译器隐藏了,因此是访问不到,但确实是被继承下去了

利用开发人员命令提示工具查看对象模型:

  1. 从开始页面找到编译器的开发人员命令提示工具

  1. 跳转盘符:F:(cpp的盘符)
  2. 跳转文件具体路径:cd 具体路径下
  3. 查看命令(查看单个布局):cl /d1 reportSingleClassLayout类名 文件名

(文件名:类所在的文件)

4、继承中构造和析构顺序

子类继承父类后,当创建子类对象,也会调用父类的构造函数

问题:

父类和子类的构造和构析顺序是谁先谁后?

结论:

  • 创建子类对象之前自动创建父类对象
  • 先构造父类,再构造子类
  • 先析构子类,再析构父类

5、继承同名成员处理方式

问题:

当子类与父类出现同名成员,如何通过子类对象访问到子类或者父类中的数据

呢?

处理方式:

同名成员属性:

  • 子类对象访问子类同名成员,直接访问即可
  • 子类对象访问父类同名成员,需要加作用域

同名成员函数:

  • 直接调用 调用的则是子类中的同名成员函数
  • 加上作用域 调用的则是父类的同名成员函数
  • 如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中的所有同名成员函数(包括有参和无参),如果想访问到父类中被隐藏的同名成员函数,需要加作用域

完整测试代码:

6、继承同名静态成员处理方式

问题:

继承中同名静态成员在子类对象上如何进行访问?

静态成员和非静态成员出现同名,处理方式一致

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域

继承中同名静态成员的两种访问方式

  1. 通过对象访问
  2. 通过类名访问

同名静态成员变量

注意:通过类名访问父类静态成员变量第一个::代表通过类名访问,第二个::代表访问父类作用域下

同名静态成员函数

7、多继承语法

C++允许一个类继承多个类

语法:

class 子类 ; 继承方式 父类1,继承方式 父类2.....

问题:

多继承可能会引发父类中有同名成员出现(如在多个继承的父类中都出现成员A),需要加分作用域

实际开发中不建议用多继承

当父类中出现同名成员,需要加作用域区分

8、菱形继承

有两个类,它们有共同的父类,也有共同的子类

概念:

  • 两个派生类继承同一个基类
  • 又有某个类同时继承两个派生类

这种继承被称为菱形继承,或者钻石继承

问题:

产生二义性

最小子类中会有两份最大基类中的数据

需要加以作用域区分

利用虚继承解决菱形继承问题

继承之前加上关键字 virtual 变为虚继承

虚基类:虚继承后最大的类称为虚基类

虚继承之后只有一份数据,所以可以不用加作用域区分

虚继承的底层

  1. 点击开始键,找到编译器文件下的开发人员命令提示符

  1. 跳转到文件所在盘符,cd到文件所在目录

  1. 输入命令dir,查看文件

  1. 输入命令cl /d1 reportSingleClassLayoutSheepTuo "08 菱形继承"

左图为虚拟继承后,右图为虚拟继承前,可以发现只继承了一份m_Age

而从Sheep和Tuo继承到的是vbptr

vbptr(虚基类指针)

vbptr指向vbtable(虚基类表),表内记录了指针和数据的偏移量,加上偏移量后可以通过指针找到唯一的数据

测试代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值