嵌入式养成计划-40----C++菱形继承--虚继承--多态--模板--异常
九十四、菱形继承
94.1 概念
- 菱形继承又称为钻石继承,
- 是由公共基类派生出多个中间子类,又由中间子类共同派生出汇聚子类,
- 汇聚子类会得到多份中间子类从公共基类继承下来的数据成员,会造成空间浪费,没有必要。
所以存在一个问题:
- 汇聚子类会得到多份中间子类从公共基类继承下来的数据成员,会造成空间浪费,没有必要。
- 会多次对公共基类的数据成员初始化,或者释放。
- 如何避免?
94.2 形式
A --------公共基类/ \
B C -------中间子类\ /D --------汇聚子类
- 上面那个问题的解决方法:
虚继承
九十五、虚继承
95.1 作用
- 使汇聚子类仅获得一份经中间子类从公共基类继承下来的数据成员。
95.2 格式
- 关键字 :
virtual - 在中间子类的继承方式前加
virtual
class 类名:virtual 继承方式 类名 //中间子类,可多继承
{中间子类自己的内容;
};
95.3 注意
- 虚继承之后,只保留一份中间子类从公共基类继承下来的数据成员,
- 但是不知道保留哪个中间子类的,所以就会自动调用公共基类的无参构造函数,
- 如果想使用公共基类的有参构造函数,则需要在汇聚子类中调用公共基类的有参构造函数。
九十六、多态
- 静态多态(在编译时加载)—> 如 :函数重载
- 动态多态(在运行时加载)
96.1 啥是多态
- 多态 :一种形式 拥有 多种状态
- 例如 :一个人,在不同环境下有着不同的状态,也有不同的 属性 和 功能
- 多态:
父类的指针或者引用,指向或者初始化子类的对象,调用子类对父类重写的函数,进而使用子类的功能。
96.2 函数重写
- 要求 :
- 两个类之间必须要有继承关系
- 子类和父类有同名同类型的函数
- 父类中的该函数必须是虚函数
96.3 虚函数
- 关键字 :
virtual
- 在函数前加 virtual ----->虚函数
- 虚函数满足继承,
如果父类中函数是虚函数,那么继承到子类中,该函数还是虚函数,
如果子类继续被继承,那么“孙类”中的该函数还虚函数…
96.4 赋值兼容规则
父类的指针或者引用,可以指向或者初始化子类的对象- 父类指针指向的仅仅只是子类中继承父类的那段空间

96.5 多态中,实现函数重写的原理
- 类中有虚函数时,虚函数都会有一个虚指针
- 虚指针在类的最前面,指向了虚函数表,虚函数表里记录虚函数
- 虚指针和虚函数表是实现多态的重要机制

96.6 虚析构函数
- 因为父类指针指向子类对象,只作用与子类从父类继承下来的那片特殊空间,
- 释放父类指针,只会把父类指针作用的那块空间释放,子类自己拓展的空间没有得到释放,从而造成内存泄漏。
虚析构函数 :如果把父类中析构函数设置成虚析构函数,那么子类拓展的空间就会被一起释放,虚析构函数也满足继承。
示例 :
#include <iostream>
using namespace std;class Person
{
private:string name;
public:Person() {}Person(string name):name(name){}virtual ~Person(){} //虚析构函数
};
class Stu:public Person
{
private:int id;
public:Stu() {}Stu(string n, int id):Person(n),id(id){}~Stu(){}
};
int main()
{Person *ptr = new Stu("zhangsan", 1001);delete ptr; //如果没有虚析构函数的话,只释放父类指针作用的空间,子类//拓展的空间并没有得到释放,会造成内存泄漏。解决方案:虚析构函数return 0;
}
96.7 纯虚函数
-
当父类中的虚函数只用来被子类重写,并且没有需要去完成的功能,那么一般将该虚函数设置成纯虚函数。
-
格式:
virtual 函数返回值类型 函数名(形参列表) = 0 ; //纯虚函数 //纯虚函数 是在父类中声明,子类中实现
96.8 抽象类
-
概念: 抽象类中至少有一个纯虚函数,抽象类不能具体的实例化一个对象,一般是用来被继承的。
不能实例化对象,只能执行子类对象 -
如果父类中有纯虚函数,表示父类是抽象类,
子类继承后,如果没有对父类中纯虚函数做重写,则子类也是一个抽象类,不能实例化一个对象。
例如 :
#include <iostream>
using namespace std;class A
{
private:int a;
public:virtual void show() = 0;//纯虚函数
};class B :public A
{
private:int b;
public:
};int main()
{//B a; 不能实例化一个对象return 0;
}
96.9 C++中虚函数与纯虚函数的区别
-
虚函数和纯虚函数可以定义在同一个类中,含有纯虚函数的类被称为抽象类,而只含有虚函数的类不能被称为抽象类。
-
虚函数可以被直接使用,也可以被子类重载以后,以多态的形式调用,而纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类有声明而没有定义。
-
虚函数和纯虚函数都可以在子类中被重载,以多态的形式被调用。
-
虚函数和纯虚函数通常存在于抽象基类之中,被继承的子类重载,目的是提供一个统一的接口。
-
虚函数的定义形式:virtual{};纯虚函数的定义形式:virtual { } = 0;在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时要求前期绑定,然而虚函数却是动态绑定,而且被两者修饰的函数生命周期也不一样。
九十七、模板
- 模板就是建立一个通用的模具,大大提高代码的复用性。
- C++除面向对象编程思想外,还有另一种编程思想,泛型编程,主要利用的技术是 模板
- C++提供了两种重要的模板机制:函数模板 和 类模板
生活中的模板 :


97.1 模板的特点
- 模板是通用的,不是万能的
- 模板只是一个框架
97.2 函数模板
97.2.1 作用
- 函数模板,就是建立一个通用的函数,
- 其返回值类型,或者参数类型不具体制定,用一个虚拟的类型来代替。
97.2.2 格式
template<typename T>
函数的定义
如 :
template <typename T>
T fun(T x, T y) //建立了一个通用的函数,实现数据类型之和
{return x+y;
}
template -------> 创建模板
typename -------> 表明其后是一种数据类型,typename还可以用class代替
T -----> 表示数据类型,也可以用其他代替
调用时 :
cout << fun(1,2) << endl;
cout << fun(1.3,1.4) << endl;
cout << fun('0', '1') << endl;
97.3 类模板
97.3.1 作用
- 建立一个通用的类, 类中的 成员变量 的类型 不具体制定,用一个虚拟类型来代替
97.3.2 格式
template<typename T>
类的定义
template -------> 创建模板
typename -------> 表明其后是一种数据类型,typename还可以用class代替
T -----> 表示数据类型,也可以用其他代替
九十八、异常
-
作用 :可以优雅的解决异常
-
实现步骤
- 用
try包裹可能产生异常的地方 - 在产生异常的条件下,用
throw抛出异常 - 在
try后面的catch语句中接收异常,并在catch后的代码块中处理异常
- 用
示例 :
#include <iostream>
using namespace std;int fun(int x, int y)
{if(y!=0){return x/y;}else{throw -1; //抛出异常}
}
int main()
{try{fun(9,0); //把可能发生异常的地方用try包裹起来cout << "hello 啊" << endl; }catch (int e){if(e == -1){cout << "分母为0,不合法" << endl;}}return 0;
}
小作业:
比喻:
动物园的讲解员和动物表演
动物园里有一位讲解员,他会为每种动物表演做简单的介绍,如狮子、大象、猴子等。提示:在这个场景中,我们可以将动物比作是不同的类,而每种动物表演则是类中的函数。讲解员则是一个基类,他可以根据每种动物的特点和表演,进行相应的介绍。
具体过程如下:定义一个基类 Animal,其中有一个虛函数perform(),用于在子类中实现不同的表演行为。
我写的
#include <iostream>
using namespace std;// base_class
class Animal
{
private:string name;
public:Animal() {}Animal(string name):name(name) {}Animal(const Animal &other):name(other.name){}Animal &operator=(const Animal &other){name = other.name;return *this;}virtual ~Animal(){}virtual void perform() = 0;string get_name(){return this->name;}
};class Lion:virtual public Animal
{
public:Lion() {}Lion(string name):Animal(name) {}Lion(const Lion &other):Animal(other){}Lion &operator=(const Lion &other){Animal::operator=(other);return *this;}~Lion(){}void perform() {cout << Animal::get_name() + " : " << "河东狮吼" << endl;}
};class Elephant:virtual public Animal
{
public:Elephant() {}Elephant(string name):Animal(name) {}Elephant(const Elephant &other):Animal(other){}Elephant &operator=(const Elephant &other){Animal::operator=(other);return *this;}~Elephant(){}void perform() {cout << Animal::get_name() + " : " << "象群践踏" << endl;}
};class Monkey:virtual public Animal
{
public:Monkey() {}Monkey(string name):Animal(name) {}Monkey(const Monkey &other):Animal(other){}Monkey &operator=(const Monkey &other){Animal::operator=(other);return *this;}~Monkey(){}void perform() {cout << Animal::get_name() + " : " << "专业偷桃" << endl;}
};int main()
{Animal *p = nullptr;Lion l("狮子狗");Elephant e("孟获");Monkey m("孙猴子");p = &l;p->perform();p = &e;p->perform();p = &m;p->perform();return 0;
}

相关文章:
嵌入式养成计划-40----C++菱形继承--虚继承--多态--模板--异常
九十四、菱形继承 94.1 概念 菱形继承又称为钻石继承,是由公共基类派生出多个中间子类,又由中间子类共同派生出汇聚子类,汇聚子类会得到多份中间子类从公共基类继承下来的数据成员,会造成空间浪费,没有必要。 所以存…...
C++入门指南:类和对象总结友元类笔记(下)
C入门指南:类和对象总结友元类笔记(下) 一、深度剖析构造函数1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 二、static成员2.1 概念2.2 特性 三、友元3.1 友元函数3.2 友元类 四、 内部类4.1 概念4.2 特征 五、拷贝对象时的一些编译器优化六、深…...
ctfshow web入门 php特性 web136-web140
1.web136 还有一种写文件的命令时tee命令 payload: : ls /|tee 1 访问1下载查看文件1发现根目录下有flag cat /f149_15_h3r3|tee 2 访问下载查看文件22.web137 call_user_func <?php class myclass {static function say_hello(){echo "He…...
sshpass传输文件提示Host key verification failed.
1. sshpass功能简述 sshpass指令可用于A服务器向B服务器传输文件或执行某些指令。 2. 传输文件指令 基本传输命令:sshpass -p 远程服务器登录密码 scp 本地路径文件 远程服务器登录用户名远程服务器IP地址:远程服务器文件保存路径 示例: sshpass -p 1…...
Maven系列第5篇:私服详解
maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能。 这是maven系列第5篇。 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部有maven完整系列的连接。 环境 maven3.6.1 …...
深入解析Spring Cloud Gateway的GlobalFilter
文章目录 摘要引言GlobalFilter的作用使用GlobalFilter默认的GlobalFilter自定义GlobalFilter 示例代码配置GlobalFilter配置文件方式代码方式 高级用法:重写GlobalFilter思路代码实现 结论参考文献 摘要 本文将详细介绍Spring Cloud Gateway中的GlobalFilter&…...
ffmpeg的重采样计算
最近在看ffmpeg的重采样计算逻辑,有一句话没大看懂 dst_nb_samples av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); ,各种请教之后,记录如下。 重采样后的总样本数 为什么要涵盖重采…...
Go HTTP 调用(上)
哈喽大家好,我是陈明勇,今天分享的内容是 Go HTTP 调用。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出&am…...
STM32Cube高效开发教程<基础篇>(一)----概述
声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。 本专栏博客参考《STM32Cube高效开发教程(基础篇)》,有意向的读者可以购买正版书籍辅助学习,本书籍由王维波老师、鄢志丹老师、王钊老师倾力打造,书籍内容干货满满。 一、 STM32系列…...
汽车RNC主动降噪算法DSP C程序实现
汽车RNC主动降噪算法C程序 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,车载...
Java21虚拟线程完整用法
方式1 Thread.startVirtualThread(new Task());方式2 Thread virtualThread Thread.ofVirtual().name("Virtual Thread").unstarted(new Task()); virtualThread.start();方式3 Thread.ofVirtual().name("Virtual Thread").start(new Task());方式4 Th…...
Vue 中的 nextTick 方法
nextTick的背景 Vue 使用虚拟 DOM(Virtual DOM)和异步更新策略来实现高效的视图更新。当你修改 Vue 实例的数据时,Vue 并不会立即更新真实的 DOM,而是将更新操作加入到队列中,在下一个事件循环周期(微任务…...
TypeScript React(上)
目录 扩展学习资料 TypeScript设计原则 TypeScript基础 语法基础 变量声明 JavaScript声明变量 TypeScript声明变量 示例 接口 (标准类型-Interface) 类型别名-Type 接口 VS 类型别名 类型断言:欺骗TS,肯定数据符合结构 泛型、<大写字母> 扩展学习…...
Linux 安全 - LSM源码分析
文章目录 前言一、简介1.1 DAC 和 MAC1.2 LSM 调用流程图 二、LSM相关数据结构2.1 struct security_hook_list2.2 union security_list_options2.3 structure security_hook_heads 三、security_bprm_check四、LSM 源码分析3.1 early_security_init3.2 security_init3.2.1 secu…...
第一次汇报相关问题
深度学习现在已经学习到了Mini-Batch,early-stop等针对特定场景优化的算法了。 代码已经实现了一个L层的神经网络的构建了 论文看了一些综述 主要思考的两个方向:云计算和嵌入式 云计算:分布式机器学习、联邦学习、服务器负载均衡等 嵌入式&…...
[产品体验] GPT4识图功能
[产品体验] GPT4识图功能 图片配文字超强的OCR能力知识问答多图解释 打开chatgpt的时候突然发现能用识图了,赶紧去体验一下,大大的震撼… 图片配文字 超强的OCR能力 我传上去的图片并不清晰… 还能准确识别,orz ! 知识问答 多…...
《3D 数学基础》几何检测-最近点
目录 1. 直线上的最近点 2. 射线上的最近点 3. 点到平面的距离 4. 圆或球上的最近点 5. AABB上的最近点 1. 直线上的最近点 q是距离q的最近点,也就是q在直线上的投影。 其中p是直线上的点(向量表示),n是直线的法向量&#x…...
动态规划 -背包问题-详解
问题 注:大佬对此类问题的解法:动态规划背包问题总结 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 示例 1ÿ…...
Bootstrap-- 媒体特性
最大、最小宽度例子: 横屏与竖屏例子: 宽度比与像素比例子:...
c# 用非递归的写法实现递归
最近写代码碰到了一个bug,就是递归次数太多爆堆栈了,然后就写了一个递归工具来解决这个问题。 using System; using System.Collections.Generic;/// <summary> /// 递归工具 /// </summary> public static class RecursionTool {//递归方式…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
