当前位置: 首页 > news >正文

C++继承与派生关键知识总结(学生学习笔记)

最近刚学完C++的继承与派生部分,这部分知识点有点多且容易混淆,比如public、protected、private三种继承方式的权限区别,还有虚函数和多态的基础关联等。为了巩固学习成果,也希望能帮到和我一样正在学习这部分内容的同学,整理了这篇关键知识总结,如有错误欢迎大家在评论区指出~

一、继承与派生的基本概念

首先要明确两个核心概念:继承和派生其实是同一个过程的两个不同视角。

  • 继承:子类(派生类)获取父类(基类)的成员变量和成员函数的过程,目的是实现代码复用,避免重复编写相同的代码。

  • 派生:父类产生子类的过程,子类可以在父类的基础上添加新的成员,或者重写父类的成员函数,实现功能的扩展。

举个简单的例子:我们有一个“Person”基类,包含姓名、年龄等成员和吃饭、睡觉等成员函数;然后可以派生出“Student”子类,Student会继承Person的所有成员,同时还能添加“学号”“班级”等专属成员,以及“上课”“考试”等专属成员函数。

二、继承的语法格式

派生类的定义语法如下,核心是指定继承方式和基类:

class 派生类名 : 继承方式 基类名1, 继承方式 基类名2, ... { // 派生类的新增成员(成员变量 + 成员函数) };

注意点:

  1. 继承方式有三种:public(公有继承)、protected(保护继承)、private(私有继承),不写默认是private继承(class关键字下,struct关键字下默认是public继承)。

  2. 支持多继承,即一个派生类可以同时继承多个基类(用逗号分隔),但多继承容易出现二义性问题,后面会提到。

三、三种继承方式的权限控制(重点难点)

这是继承部分最核心的知识点之一!关键是理解:基类成员在派生类中的访问权限,由“基类中成员的访问权限”和“继承方式”共同决定。

先回顾基类成员的三种访问权限:

  • public成员:基类内外都可访问;

  • protected成员:基类内可访问,基类外不可访问,但派生类内可访问;

  • private成员:只能在基类内访问,基类外和派生类内都不可访问(派生类无法直接访问基类的private成员)。

三种继承方式对权限的影响总结如下:

基类成员权限

public继承

protected继承

private继承

public

派生类中为public(派生类内外均可访问)

派生类中为protected(派生类内可访问,外不可)

派生类中为private(仅派生类内可访问)

protected

派生类中为protected

派生类中为protected

派生类中为private

private

派生类中不可访问

派生类中不可访问

派生类中不可访问

核心记忆口诀:无论哪种继承,基类private成员都无法被派生类访问;继承方式的权限是“取小原则”——派生类中成员的最终权限,取基类成员权限和继承方式权限中更严格的那个(public > protected > private)。

举个例子:基类的public成员,用protected继承,最终在派生类中是protected权限;基类的protected成员,用private继承,最终在派生类中是private权限。

四、派生类的构造函数与析构函数

派生类继承了基类的成员,但基类的构造函数和析构函数不会被继承,需要注意派生类对象创建和销毁时的调用顺序。

1. 构造函数的调用顺序

创建派生类对象时,会先调用基类的构造函数,再调用派生类的构造函数。如果是多继承,基类构造函数的调用顺序由派生类定义时“基类的声明顺序”决定,而非初始化列表中的顺序。

语法:如果基类没有默认构造函数(无参构造),派生类的构造函数必须在初始化列表中显式调用基类的带参构造函数。

// 基类 class Base { public: Base(int a) : m_a(a) {} // 带参构造,无默认构造 private: int m_a; }; // 派生类 class Derived : public Base { public: // 必须在初始化列表中显式调用Base的带参构造 Derived(int a, int b) : Base(a), m_b(b) {} private: int m_b; };

2. 析构函数的调用顺序

销毁派生类对象时,顺序与构造相反:先调用派生类的析构函数,再调用基类的析构函数。

注意:如果基类的析构函数不是虚函数,当用基类指针指向派生类对象并删除该指针时,只会调用基类的析构函数,不会调用派生类的析构函数,可能导致内存泄漏。因此,基类的析构函数建议声明为虚函数(后面虚函数部分会详细说)。

五、继承中的二义性问题

二义性是指派生类中出现了多个基类的同名成员,导致访问时无法确定访问的是哪个基类的成员,常见于多继承场景。

1. 常见二义性场景

  • 多继承时,多个基类有同名成员(成员变量或成员函数),派生类直接访问该成员会报错;

  • 菱形继承(钻石继承):类A派生出类B和类C,类D同时继承类B和类C,此时类D会继承两份类A的成员,访问类A的成员时会出现二义性。

2. 解决方法

  • 显式指定访问哪个基类的成员:派生类对象.基类名::成员名

  • 解决菱形继承二义性:使用虚继承(在基类继承时加上virtual关键字),让派生类只继承一份基类的成员。语法:

    class B : virtual public A、class C : virtual public A

六、虚函数与多态(继承的核心应用)

多态是C++的三大特性之一(封装、继承、多态),而虚函数是实现多态的基础。这里只总结与继承相关的核心点,多态的详细应用可以后续再整理。

1. 虚函数的定义

在基类的成员函数声明前加上virtual关键字,该函数就是虚函数。派生类可以重写(覆盖)该虚函数(函数名、参数列表、返回值必须完全相同,除了协变情况,这里不展开)。

class Base { public: virtual void show() { // 虚函数 cout << "Base::show()" << endl; } }; class Derived : public Base { public: void show() override { // 重写虚函数,override关键字可选,用于检查重写是否正确 cout << "Derived::show()" << endl; } };

2. 多态的实现条件

  • 有继承关系;

  • 基类中有虚函数,派生类重写该虚函数;

  • 用基类指针或引用指向派生类对象,通过指针或引用调用虚函数。

Base* ptr = new Derived(); ptr->show(); // 调用的是Derived::show(),而非Base::show(),这就是多态 delete ptr;

3. 纯虚函数与抽象类

如果基类的虚函数只声明不定义,并且在声明时加上=0,该函数就是纯虚函数。包含纯虚函数的类叫做抽象类。

class Base { public: virtual void show() = 0; // 纯虚函数 };

抽象类的特点:

  • 不能直接实例化对象;

  • 派生类必须重写抽象类中的所有纯虚函数,否则派生类也会成为抽象类,无法实例化。

七、继承的常见误区与注意事项

  1. 不要为了代码复用而盲目继承:继承的核心是“is-a”关系(比如Student is a Person),如果是“has-a”关系(比如Car has a Engine),应该用组合而非继承。

  2. 基类的析构函数尽量声明为虚函数:避免用基类指针删除派生类对象时出现内存泄漏。

  3. 避免多继承:多继承容易引发二义性,除非必要,优先使用单继承 + 组合的方式。

  4. 派生类不能访问基类的private成员:如果需要访问,可以将派生类声明为基类的友元,或者在基类中提供public/protected的接口函数。

总结

C++继承与派生的核心是“代码复用 + 功能扩展”,关键知识点包括三种继承方式的权限控制、构造/析构函数的调用顺序、二义性问题的解决,以及虚函数与多态的实现。这部分内容是后续学习STL、面向对象设计模式的基础,需要多敲代码练习才能真正掌握。

最后,再次欢迎大家指出错误,也希望这篇总结能帮到正在学习的小伙伴们!一起加油~

http://www.jsqmd.com/news/161072/

相关文章:

  • 大模型Token计费单位解析:input vs output差异说明
  • 一汽大众汽车前束检测培训系统
  • SpringBoot从0-1集成腾讯音视频通话
  • BLIP图像描述生成:PyTorch-CUDA-v2.7应用场景拓展
  • BART摘要生成实战:PyTorch-CUDA-v2.7端到端流程
  • Swin Transformer部署:PyTorch-CUDA-v2.7移动端优化
  • Triton推理服务器集成:PyTorch-CUDA-v2.7生产环境实践
  • 树莓派4B安装PyTorch有多难?不如选用专用边缘计算镜像
  • Zero Redundancy Optimizer应用:降低PyTorch-CUDA-v2.7内存占用
  • 如何清理PyTorch-CUDA-v2.7镜像缓存节省空间?
  • IP 地址与 MAC 地址基础知识总结
  • 个人开发者如何低成本获取GPU算力?PyTorch镜像+云服务组合拳
  • 金融风控模型训练:PyTorch-CUDA-v2.7处理海量交易数据
  • 如何提交PR到PyTorch官方仓库?参与开源贡献第一步
  • T型与NPC型三电平SVPWM的拓扑切换与算法生成技术研究,实时优化大小扇区与时间分配,实现1...
  • 信创目录纳入进展:PyTorch生态国产化替代路线图
  • 学术论文复现实验:PyTorch-CUDA-v2.7保证结果可重现
  • 基于 Docker 和 MCSManager 搭建 SteamCMD 游戏服务器
  • 让机器像人一样流畅写作的AI技术探索
  • 飞腾CPU+DCU组合适配:PyTorch-CUDA-v2.7移植可能性探讨
  • LangGraph流程编排:构建复杂AI工作流的基础环境
  • AdamW优化器实战:PyTorch-CUDA-v2.7默认推荐配置
  • 指标管理的AI自治之路:衡石平台如何实现异常检测、血缘分析与智能推荐的自动化治理
  • AutoGPT项目部署:PyTorch-CUDA-v2.7赋能自主代理
  • 各模态丝滑衔接的原理和方法
  • ue重定向学习笔记
  • PyTorch-CUDA-v2.7镜像签名验证:确保来源可信
  • BERT微调中文分类任务:PyTorch-CUDA-v2.7实战教程
  • Python处理Abaqus(ODB文件)的结果
  • DiskInfo监控SSD寿命:保障GPU服务器长期稳定运行