c++ 重写 多态
1 重写(继承后(拼接基类后))
1.1 非虚函数 同名成员函数 (各自有一个xFunction() 内存 )
#include <iostream>
#include <String>
class BaseClass {
public:void xFunction() {std::cout << "BaseClass::xFunction()\n"; }
};class Subclass1 : public BaseClass {
public:void xFunction() {std::cout << "Subclass1::xFunction()\n";}
};int main() {Subclass1 subclass1;subclass1.xFunction();return 0;
}
输出:
Subclass1::xFunction()
基类对象内存布局:
+-------------+
| 其他成员变量 |
+-------------+
| xFunction() | -> 基类xFunction()函数的代码
+-------------+子类对象内存布局:
+-------------+
| 基类部分 | // 继承而来的基类的数据和方法
+-------------+
| 子类独有成员变量 |
+-------------+
| xFunction() | -> 子类xFunction()函数的代码
+-------------+
运行原则是:
- 子类对象可以直接访问继承而来的基类的数据和方法
- 当子类与基类存在同名函数时,根据就近原则,通过子类对象访问同名函数时,会调用子类自己的同名函数,即这里的Subclass1::xFunction()
- 如果要访问基类中被隐藏的同名函数,需要使用作用域解析运算符,如subclass1.BaseClass::xFunction()
所以在这个例子中,通过subclass1.xFunction()调用时,执行的就是子类中重写的xFunction()函数,输出"Subclass1::xFunction()"。
1.1.2 多次实例化subclass1对象 (就是多次创建应用这个类 开内存)
每个实例化对像的成员变量 内存是单独的
成员函数是多个此类实例对象 公用子类 基类的成员函数 用类:: 指明
成员函数代码区(共享):┌──────────────────────────────┐
│ 成员函数代码 │
│ (包括 BaseClass::xFunction) │
│ (包括 Subclass1::xFunction) │
└──────────────────────────────┘subclass1对象实例1:
┌──────────────────────────────┐
│ 成员变量 │
└──────────────────────────────┘subclass1对象实例2:
┌──────────────────────────────┐
│ 成员变量 │
└──────────────────────────────┘
1.2 虚函数virtual (只有一个xFunction()内存 在基类中, 重写就覆盖)
#include <iostream>
#include <String>
class BaseClass {
public:virtual void xFunction() {std::cout << "BaseClass::xFunction()\n"; }
};class Subclass1 : public BaseClass {
public:void xFunction() {std::cout << "Subclass1::xFunction()\n";}
};int main() {Subclass1 subclass1;subclass1.xFunction();return 0;
}
+------------------------+
| subclass1 |
+------------------------+
| vptr (指向虚函数表) |
+------------------------+
| |
| |
| |
| |
| |
| |
| |
| |
+------------------------++------------------------+
| BaseClass |
+------------------------+
| vtable (虚函数表) |
+------------------------+
| xFunction() |
+------------------------+就是subclass1存的是基类的xFunction()地址的地址?是的,您的理解是正确的。
subclass1中存的是指向基类中xFunction()这个成员函数的指针的地址。
所以它是一个二级指针。
2 多态(子类用基类模板创建/增加不同功能)
#include <iostream>class Operation {
public:virtual int calculate(int a, int b) = 0; // 纯虚函数,需要在子类中实现
};class Addition : public Operation {
public:int calculate(int a, int b) override {return a + b;}
};class Subtraction : public Operation {
public:int calculate(int a, int b) override {return a - b;}
};int main() {Operation* op1 = new Addition(); // 创建加法类对象,并将其指针赋值给基类指针Operation* op2 = new Subtraction(); // 创建减法类对象,并将其指针赋值给基类指针int result1 = op1->calculate(5, 3); // 调用加法类的calculate函数int result2 = op2->calculate(5, 3); // 调用减法类的calculate函数std::cout << "Result1: " << result1 << std::endl; // 输出加法计算结果std::cout << "Result2: " << result2 << std::endl; // 输出减法计算结果delete op1;delete op2;return 0;
}
Operation* op1 = new Addition(); 创建对象并开内存 并给基类一个初始地址,;
然后根据这个地址 基类分配各个成员的空间;
初始化完 基类Operation被改造有成员变量calculate();
子类 只有指向基类的地址 用于找到虚函数 成员变量;
+------------------------+
| Operation |
+------------------------+
| vtable (虚函数表) |
+------------------------+
| calculate() |
+------------------------++------------------------+
| Subtraction |
+------------------------+
| vptr (指向虚函数表) |
+------------------------+
3
3.1
Operation* op1 = new Addition();
3.2 & 取地址符号
Addition add; // 创建命名的 Addition 对象
Operation* op1 = &add; // 将对象的地址赋值给基类指针
是的,Operation* op1 = new Addition();这一行代码是在堆内存上动态分配了一个Addition对象。
具体来说:
new Addition() 在堆内存上创建了一个Addition对象,并返回该对象的地址
Operation* op1 定义了一个Operation类型的指针op1
= 将new Addition()返回的Addition对象的地址赋值给了指针op1
所以,op1指向了堆内存中动态分配的那个Addition对象。
而Addition add这行代码是在栈内存上创建了一个Addition类型的对象add。
两者的区别在于:
- new创建的是在堆内存上的对象
- 直接创建如Addition add的是在栈内存上的对象
堆内存对象的生命周期由程序员控制,栈内存对象的生命周期随着函数的结束而结束。
将Addition对象的地址赋值给Operation*类型的指针op1,实现了基类指针指向子类对象的效果,可以实现多态。这是面向对象编程中非常重要的概念。
相关文章:
c++ 重写 多态
1 重写(继承后(拼接基类后)) 1.1 非虚函数 同名成员函数 (各自有一个xFunction() 内存 ) #include <iostream> #include <String> class BaseClass { public:void xFunction() {std::cout << "BaseClass::xFunction()\n"; } };class Subclass1 …...
Git如何修改提交(commit)用户名称(user.name)和邮箱(user.email)
Git用户名 Git查看用户名 git config user.name修改Git提交用户名 修改全局Git用户名 git config --global user.name "xx" 修改当前服务/项目Git用户名 git config user.name "xx"如果出现以下错误,解决方案如下: 错误案例&am…...
知行之桥EDI系统HTTP签名验证
本文简要概述如何在知行之桥EDI系统中使用 HTTP 签名身份验证,并将使用 CyberSource 作为该集成的示例。 API 概述 首字母缩略词 API 代表“应用程序编程接口”。这听起来可能很复杂,但真正归结为 API 是一种允许两个不同实体相互通信的软件。自开发以…...
C++ DAY08 异常
概念 异常事件(如:除 0 溢出,数组下标越界,所要读取的文件不存在 , 空指针,内存不足 等等) 在 C 语言对错误的处理是两种方法: 一是使用整型的返回值标识错误; 二是使用 errn…...
vscode导入STM32CubeIDE工程文件夹未定义警告清除方法
0 前言 在我们使用vscode去编辑STM32CubeIDE的工程文件时,经常会出现一些类型未定义、头文件路径无效的问题,无法正常使用且非常影响观感。本文介绍如何设置vscode导入的STM32CubeIDE配置文件,解决这一问题。 1 vscode导入STM32CubeIDE工程…...
SparkSQL之Optimized LogicalPlan生成过程
经过Analyzer的处理,Unresolved LogicalPlan已经解析成为Analyzed LogicalPlan。Analyzed LogicalPlan中自底向上节点分别对应Relation、Subquery、Filter和Project算子。 Analyzed LogicalPlan基本上是根据Unresolved LogicalPlan一对一转换过来的,…...
Java中有几种基本数据类型以及转换方式【Java面经(1)】
问:Java中有几种基本数据类型呢?以及它们之间的转换方式。详细介绍下 总共有8种基本数据类型 byte 、short 、long 、float 、double 、boolean 、char 详细类型以及字节数: 基本数据类型的转换方式 自动类型转换:小–>大 byt…...
JVM虚拟机:JVM调优第一步,了解JVM常用命令行参数
本文重点 从本文课程开始,我们将用几篇文章来介绍JVM中常用的命令行的参数,这个非常重要,第一我们可以通过参数了解JVM的配置,第二我们可以通过参数完成对JVM的调参。以及后面的JVM的调优也需要用到这些参数,所以我们…...
CSS特效019:图标图片悬浮旋转一周
CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧,主要包含CSS布局,CSS特效,CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点,CSS特效主要是一些动画示例,CSS花边是描述了一些CSS…...
requests请求django接口跨域问题处理
参考: https://zhuanlan.zhihu.com/p/416978320 https://blog.csdn.net/SweetHeartHuaZai/article/details/130983179 使用httpx代替requests import httpxheaders {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.3…...
#Js篇:Promise
定义 Promise是异步操作解决方案,为异步操作提供统一接口。 Promise英文意思是“承诺”,表示其他手段无法改变。 返回 所有异步任务都返回一个Promise实例。 Promise实例有一个then方法,用于指定下一步的回调函数。 状态 异步操作未完…...
【数据库篇】关系模式的表示——(2)规范化
范式:范式是符合某一种级别的关系模式的集合 规范化:是指一个低一级的范式的关系模式,通过模式的分解转换为若干个高一级范式的关系模式的集合。 1NF 每个分量必须是不可分开的数据项,满足这个条件的关系模式就是1NF。 2NF 若…...
【C++那些事儿】类与对象(3)
君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,我之前看过一套书叫做《明朝那些事儿》,把本来枯燥的历史讲的生动有趣。而C作为一门接近底层的语言,无疑是抽象且难度颇…...
spark的算子
spark的算子 1.spark的单Value算子 Spark中的单Value算子是指对一个RDD中的每个元素进行操作,并返回一个新的RDD。下面详细介绍一些常用的单Value算子及其功能: map:逐条映射,将RDD中的每个元素通过指定的函数转换成另一个值&am…...
【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷7
1、一袋小球中有15个白球,3个红球和2个黑球。在随机从袋子中拿出至少()个小球后,才可以保证至少拿出了5个白球 A、5 B、10 C、8 D、15 答案:B 2、以下选项中,数值最接近十进制数114的是( &…...
MySQL MHA高可用架构搭建
快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解(如有不正确的地方欢迎各位小伙伴在评论区提意见,博主会及时修改) MySQL MHA高可用架构搭建 MHA(Master HA)是一款开源的 MySQL 的高可用程序…...
UE小计:顶部工具栏按钮添加下拉列表,大纲列表、资源管理窗口右键添加按键
下拉列表 void FYouPluginsModule::StartupModule() {FYouToolStyle::Initialize();FYouToolStyle::ReloadTextures();FYouToolCommands::Register();PluginCommands MakeShareable(new FUICommandList);PluginCommands->MapAction(FYouToolCommands::Get().PackByCloudAc…...
git stash 用法总结
目录 1,介绍场景1:场景2: 2,常用命令2.1,基础2.2,进阶1,存储时指定备注2,通过索引来操作指定的存储3,修改存储规则 2.3,查看 stash 修改的具体内容 1…...
Linux操作系统之apt常用命令记录
文章目录 apt 命令apt 语法apt 常用命令列出所有可更新的软件清单命令升级软件包列出可更新的软件包及版本信息升级软件包,升级前先删除需要更新软件包安装指定的软件命令:安装多个软件包:更新指定的软件命令显示软件包具体信息,例如…...
TCP 重传、滑动窗口、流量控制、拥塞控制的剖析
TCP 是一个可靠传输的协议,那它是如何保证可靠的呢? 为了实现可靠性传输,需要考虑很多事情,例如数据的破坏、丢包、重复以及分片顺序混乱等问题。如不能解决这些问题,也就无从谈起可靠传输。 那么,TCP 是…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
