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

C++类的继承关系中什么时候要用到上行转换和下行转换

一、C++类继承关系中的上行转换

1. 多态性实现

       在C++中,上行转换(将派生类转换为基类)是实现多态性的关键。例如,当有一个基类`Animal`,以及派生类`Dog`和`Cat`。如果有一个函数接受`Animal`类型的参数,我们可以将`Dog`或`Cat`的对象作为参数传递给这个函数,这就是上行转换。这样做的好处是,我们可以编写更通用的代码,处理不同类型的对象,而不需要为每个派生类编写单独的函数。这种转换是隐式的,不需要显式的类型转换操作符。代码示例如下:

class Animal { 
public: virtual void makeSound() {} 
}; class Dog : public Animal { 
public: void makeSound() override { // 狗叫的实现 } 
}; class Cat : public Animal { 
public: void makeSound() override { // 猫叫的实现 } 
}; // 函数接受Animal类型的参数 
void animalSound(Animal& animal) { animal.makeSound(); 
} int main() { Dog dog; Cat cat; animalSound(dog); // 隐式地将Dog对象转换为Animal类型 animalSound(cat); // 隐式地将Cat对象转换为Animal类型 return 0; 
} 

2. 简化代码结构

       当处理一组具有继承关系的类时,我们可以将派生类对象当作基类对象来处理,从而简化代码的逻辑结构。例如,在一个图形绘制系统中,有基类`Shape`,派生类`Circle`、`Rectangle`等。如果我们有一个函数用于计算所有形状的总面积,我们可以将不同的派生类对象当作`Shape`对象进行处理,不需要为每个派生类单独编写计算总面积的函数。

3. 代码的可扩展性

       方便在已有的代码基础上添加新的派生类。假设我们有一个游戏角色系统,基类是`Character`,已经有派生类`Warrior`和`Mage`。如果我们要添加一个新的派生类`Archer`,由于可以进行上行转换,新的`Archer`类可以很容易地集成到现有的系统中,只要`Archer`类遵循`Character`类的接口规范,就可以在接受`Character`类型的地方使用`Archer`类的对象,而不需要对现有的处理`Character`类型的函数进行大量修改。

二、C++类继承关系中的下行转换

1. 特定类型操作

       当我们有一个基类指针或引用指向一个派生类对象,并且我们知道这个对象的实际派生类型,想要调用派生类特有的成员函数或访问派生类特有的成员变量时,就需要进行下行转换。例如,在前面提到的`Animal`类及其派生类的例子中,如果我们有一个函数接收`Animal`类型的指针,并且我们知道这个指针实际上指向的是`Dog`对象,我们想要调用`Dog`类特有的函数(比如`Dog`类有一个`fetch`函数,`Animal`类没有),就需要将`Animal`指针下行转换为`Dog`指针。但是,下行转换需要显式地使用`dynamic_cast`,并且要求基类有虚函数。示例代码如下: 

class Animal { 
public: virtual void makeSound() {} 
}; class Dog : public Animal { 
public: void makeSound() override { // 狗叫的实现 } void fetch() { // 取东西的实现 } 
}; void specialFunction(Animal* animal) { Dog* dog = dynamic_cast(animal); if (dog!= nullptr) { dog->fetch(); } 
} int main() { Dog dog; specialFunction(&dog); return 0; 
} 

2. 恢复对象的真实类型

       在某些情况下,我们可能将派生类对象向上转换后存储在基类容器(如`vector`)中,当我们从容器中取出对象时,它们是基类类型,但我们可能需要根据实际情况将它们恢复为原来的派生类类型,以便进行派生类特定的操作,这时候就需要下行转换。例如,在一个图形编辑系统中,我们将不同类型的图形对象(`Circle`、`Rectangle`等派生类)向上转换为`Shape`类型并存储在一个容器中。当用户选择某个图形进行编辑时,我们从容器中取出对象,通过下行转换将其恢复为原来的派生类类型,然后调用派生类特有的编辑函数。

3. 增强代码的灵活性

       下行转换可以让我们在遵循类型安全的前提下,更灵活地处理具有继承关系的对象。例如,在一个插件系统中,插件可能派生自一个公共的基类,主程序通过基类接口与插件交互,但在某些情况下,主程序可能需要根据插件的具体类型(通过下行转换确定)来提供不同的用户界面或额外的功能。

相关文章:

C++类的继承关系中什么时候要用到上行转换和下行转换

一、C类继承关系中的上行转换 1. 多态性实现 在C中,上行转换(将派生类转换为基类)是实现多态性的关键。例如,当有一个基类Animal,以及派生类Dog和Cat。如果有一个函数接受Animal类型的参数,我们可以将Dog或…...

Ubuntu 22.04永久保存路由

在 Ubuntu 22.04 上,可以按照以下方式配置让流量访问 172.19.201.207 走指定的路由。 1. 临时添加路由 临时路由规则只在当前系统会话中有效,重启后会丢失。 添加路由规则 运行以下命令: sudo ip route add 172.19.201.207 via 192.168.2…...

数据结构十大排序之(冒泡,快排,并归)

接上期: 数据结十大排序之(选排,希尔,插排,堆排)-CSDN博客 前言: 在计算机科学中,排序算法是最基础且最重要的算法之一。无论是大规模数据处理还是日常的小型程序开发,…...

OpenFeign源码

openfeign是通过FeignClientFactoryBean生成动态代理对象的方式实现http客户端无感调用,可以做到像定义接口一样写http客户端调用代码。 配置Feign接口后,我们通常会在SpringBoot项目启动类上标记EnableFeignClients,这个是生成动态代理对象的…...

sql server索引优化语句

第一步 建一个测试表 --create table TestUsers --( -- Id int primary key identity(1,1), -- Username varchar(30) not null, -- Password varchar(10) not null, -- CreateDateTime datetime not null --)第二步 插入100w数据 大概1分钟执行时间 ----插入数据…...

深度学习之超分辨率算法——SRGAN

更新版本 实现了生成对抗网络在超分辨率上的使用 更新了损失函数,增加先验函数 SRresnet实现 import torch import torchvision from torch import nnclass ConvBlock(nn.Module):def __init__(self, kernel_size3, stride1, n_inchannels64):super(ConvBlock…...

16.2、网络安全风险评估技术与攻击

目录 网络安全风险评估技术方法与工具 网络安全风险评估技术方法与工具 资产信息收集,可以通过调查表的形式把我们各类的资产信息进行一个统计和收集,掌握被评估对象的重要资产分布,进而分析这些资产关联的业务面临的安全威胁以及存在的安全…...

【项目管理】GDB调试

gdb(GNU Debugger) 是 Linux 和嵌入式开发中最常用的调试工具之一,可以用来调试 C/C 程序、排查崩溃、分析程序流程等。在嵌入式开发中,gdb 还可以通过远程调试(gdbserver)调试目标设备上的程序。 这篇文章…...

ChatGPT生成接口测试用例(一)

用ChatGPT做软件测试 接口测试在软件开发生命周期中扮演着至关重要的角色,有助于验证不同模块之间的交互是否正确。若协议消息被恶意修改,系统是否能够恰当处理,以确保系统的功能正常运行,不会出现宕机或者安全问题。 5.1 ChatGP…...

2024 年 IA 技术大爆发深度解析

摘要: 本文旨在深入剖析 2024 年 IA 技术大爆发所引发的多方面反响。通过对产业变革、经济影响、就业市场、社会影响、政策与监管以及未来展望等维度的探讨,揭示 IA 技术在这一关键时期对全球各个层面带来的深刻变革与挑战,并提出相应的思考与…...

如何进行js后台框架搭建(树形菜单,面包屑,全屏功能,刷新功能,监听页面刷新功能)

框架功能是后台高亮不可缺少的功能,基本上所有的后台都需要框架功能,下面是我制作好的一个效果图 下面是我的框架里面功能的具体讲解,还有完整的代码示例 1.声明的变量 // 声明一个用于判断个人信息显示变量 let myes 0; // 声明一个用于切…...

多目标优化常用方法:pareto最优解

生产实际中的许多优化问题大都是多目标问题,举个例子:我们想换一份工资高、压力小、离家近的新工作,这里工资高、压力小、离家近就是我们的目标,显然这是一个多目标问题,那我们肯定想找到这三个目标同时最优的工作&…...

Vue.js实例开发-如何通过Props传递数据

props 是父组件用来传递数据给子组件的一种机制。通过 props,你可以将数据从父组件“传递”到子组件,并在子组件的模板和逻辑中使用这些数据。 1. 定义子组件并接收 props 首先,定义一个子组件,并在该组件中声明它期望接收的 pr…...

由popover框一起的操作demo问题

场景: 当popover框弹出的时候,又有MessageBox 提示,此时关闭MessageBox 提示,popover就关闭了。将popover改为手动激活,可以解决这个问题,但是会引起另外一个问题,之前(click触发的时…...

人工智能ACA(四)--机器学习基础

零、参考资料 一篇文章完全搞懂正则化(Regularization)-CSDN博客 一、 机器学习概述 0. 机器学习的层次结构 学习范式(最高层) 怎么学 监督学习 无监督学习 半监督学习 强化学习 学习任务(中间层&#xff0…...

uniapp图片数据流���� JFIF ��C 转化base64

1,后端返回的是图片数据流,格式如下 ���� JFIF ��C 如何把这样的文件流转化为base64, btoa 是浏览器提供的函数,但在 小程序 环境中(如微信小程序…...

django中cookie与session的使用

一、cookie cookie由服务器生成 ,存储在浏览器中的键值对数据,具有不安全性,对应敏感数据应该加密储存在服务端每个域名的cookie相互独立浏览器访问域名为A的url地址,会把A域名下的cookie一起传递到服务器cookie可以设置过期时间 django中设…...

<项目代码>YOLO Visdrone航拍目标识别<目标检测>

项目代码下载链接 <项目代码>YOLO Visdrone航拍目标识别<目标检测>https://download.csdn.net/download/qq_53332949/90163918YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一…...

GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录

文章目录 论文背景Spectre-PHT(Transient Execution )Concurrency BugsSRC/SCUAF和实验条件 流程Creating an Unbounded UAF WindowCrafting Speculative Race ConditionsExploiting Speculative Race Conditions poc修复flush and reload 论文 https:/…...

OPPO 数据分析面试题及参考答案

如何设计共享单车数据库的各个字段? 对于共享单车的数据库设计,首先考虑用户相关的字段。用户表可以包含用户 ID,这是一个唯一标识符,用于区分不同用户;姓名,记录用户的真实姓名;联系方式,比如手机号码,方便在出现问题时联系用户;注册时间,记录用户何时开始使用共享…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...