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

一次基类类型对象无法被传递问题的分析

看下面一段代码:


// proj2.cpp
#include <iostream>
using namespace std;
class CharShape {
public:CharShape(char ch) : _ch(ch) {};virtual void Show() = 0;
protected:char _ch;   // 组成图形的字符
};
class Triangle : public CharShape {
public:Triangle(char ch, int r) : CharShape(ch), _rows(r) {}void Show();
private:int _rows;  // 行数
};
class Rectangle : public CharShape {
public:Rectangle(char ch, int r, int c) :CharShape(ch), _rows(r), _cols(c) {}void Show();
private:int _rows, _cols;   // 行数和列数
};
void Triangle::Show()  // 输出字符组成的三角形
{for (int i = 1; i <= _rows; i++) {for (int j = 1; j <= i; j++)cout << _ch;cout << endl;}
}void Rectangle::Show()  // 输出字符组成的矩形
{for (int i = 1; i <= _rows; i++) {for (int j = 1; j <= _cols; j++)cout << _ch;cout << endl;}
}//********Error********  为fun函数添加形参
void fun(CharShape cs) { cs.Show(); }
int main()
{Triangle tri('*', 4);Rectangle rect('#', 3, 8);fun(tri);fun(rect);return 0;
}

void fun(CharShape cs) { cs.Show(); } 这行代码无法正常工作,CharShape 类型的对象无法被传递。

那么如何正确地通过函数传递 CharShape 类型的对象。首先,让我们分析为什么 void fun(CharShape cs) { cs.Show(); } 不工作,而 void fun(CharShape& cs) { cs.Show(); } 可以。

问题分析
值传递 (void fun(CharShape cs) { cs.Show(); })
当你使用值传递时,你实际上是在传递 CharShape 对象的一个副本到 fun 函数中。因为 CharShape 类包含一个纯虚函数 Show(),它是一个抽象类,不能被直接实例化。因此,当你试图传递 Triangle 或 Rectangle 的对象(它们都是 CharShape 的派生类)到 fun 函数时,会发生切片(slicing)现象,即只复制了基类 CharShape 的部分(不包括派生类的任何成员),并且因为基类是一个抽象类,所以无法直接创建这个副本。

此外,即使 CharShape 不是抽象的,传递基类对象副本到 fun 函数也不会调用派生类的 Show() 方法,因为函数内部处理的是基类对象,它只知道基类的 Show() 方法(如果存在的话)。

引用传递 (void fun(CharShape& cs) { cs.Show(); })
当你使用引用传递时,你实际上是在传递对象的引用(而不是副本)到 fun 函数中。因此,函数内部操作的是原始对象,而不是它的副本。这意味着你可以传递 Triangle 或 Rectangle 的对象到 fun 函数,并且因为 Show() 方法在派生类中被重写(overridden),所以当你调用 cs.Show(); 时,会调用相应派生类的 Show() 方法。

解决方案
使用引用传递(即 void fun(CharShape& cs) { cs.Show(); })是正确的做法,因为这样可以确保你操作的是原始对象,并且可以正确地调用派生类的 Show() 方法。

另外,注意 fun 函数现在接受一个对 CharShape 的引用,这意味着你不能传递一个临时对象(比如 fun(Triangle(‘*’, 4)); 这样的直接构造调用)给 fun,因为临时对象不能被引用。但在你的 main 函数中,你已经正确地创建了 Triangle 和 Rectangle 的对象,并将它们的引用传递给了 fun 函数。

相关文章:

一次基类类型对象无法被传递问题的分析

看下面一段代码&#xff1a; // proj2.cpp #include <iostream> using namespace std; class CharShape { public:CharShape(char ch) : _ch(ch) {};virtual void Show() 0; protected:char _ch; // 组成图形的字符 }; class Triangle : public CharShape { public:Tr…...

windows设置Redis服务后台自启动

问题 在日常开发过程中&#xff0c;redis是我们常用的缓存工具&#xff0c;但是由于redis对于Linux系统进行开发的&#xff0c;在Linux系统里可以通过修改redis.conf从而从而实现后台启动。 daemonize no 改成 daemonize yes 但是在window上如何也进行后台运行呢&#xff0c…...

掌握Linux常用命令,扫平面试需求障碍

cd 切换目录。 > cd ../ #切换到父级目录 > cd /tmp # 切换到/tmp目录 > cd ~ # 切换到当前用户的家目录 ls命令 查看文件与目录的命令&#xff0c;list 的缩写。 > ls -l #列出长数据串&#xff0c;包含文件的属性与权限数据等 > ls -a #列出隐藏…...

c语言之文件打开模式

在c语言中&#xff0c;文件打开模式如下 r读模式: 允许对文件读取信息。若文件不存在&#xff0c;则会报错 w写模式&#xff1a; 允许向文件写入信息&#xff0c;若文件不存在&#xff0c;则创建一个文件 #include<stdio.h>int main() {FILE *fp;int i;char ay;fpfo…...

与禹老师学前端vue3学习汇总

24.5.15&#xff1a; 创建Vue3工程 1.确定自己电脑有没有nodejs环境&#xff0c;在cmd中输入node&#xff0c;如果出现Node.js的版本号说明已经有这个环境了&#xff0c;否则搜索Node.js安装 2.先在D盘创建一个文件夹Vue3_Study&#xff0c;然后在这个空文件夹中右键选择终端…...

Linux网络编程——HTTP协议的理解与运用

目录 前言 一、认识URL 二、认识HTTP样例 三、HTTP的报头内容 1.url 2. Content-Type 3.Method 方法 1.GET方法 2.POST方法 4、状态码 5.cookie和session 前言 我们知道&#xff0c;协议就是一种约定&#xff0c;客户端与服务端统一的用这种约定进行传输数据。我们…...

RestTemplate接口请求发送json、form数据格式以及处理接口错误状态码400 null

在使用RestTemplate发送HTTP请求时&#xff0c;你可以通过不同的方式发送JSON或表单数据&#xff08;application/x-www-form-urlencoded&#xff09;。同时&#xff0c;处理接口错误状态码&#xff08;如400&#xff09;和返回null的情况也是很重要的。以下是一些示例代码&…...

《Python编程从入门到实践》day29

# 昨日知识点回顾 修改折线图文字和线条粗细 矫正图形 使用内置格式 # 今日知识点学习 15.2.4 使用scatter()绘制散点图并设置样式 import matplotlib.pyplot as plt import matplotlib matplotlib.use(TkAgg)plt.style.use(seaborn-v0_8) # 使用内置格式 fig, ax plt.subpl…...

UIKit之图片浏览器

功能需求 实现一个图片浏览器&#xff0c;点击左右按钮可以切换背景图&#xff0c;且更新背景图对应的索引页和图片描述内容。 分析&#xff1a; 实现一个UIView的子类即可&#xff0c;该子类包含多个按钮。 实现步骤&#xff1a; 使用OC语言&#xff0c;故创建cocoa Touch类…...

如何查看SNMP设备的OID

什么是OID和MIB OID OID 代表对象标识符。 OID 唯一地标识 MIB 层次结构中的托管对象。 这可以被描述为一棵树&#xff0c;其级别由不同的组织分配。MIB MIB&#xff08;管理信息基&#xff09;提供数字化OID到可读文本的映射。 使用MIB Browser扫描OID 我的设备是一台UPS SN…...

什么?你设计接口什么都不考虑?

如果让你设计一个接口&#xff0c;你会考虑哪些问题&#xff1f; 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空&#xff0c;入参的长度限制是多少&#xff0c;入参的格式限制&#xff0c;如邮箱格式限制 返回值是否为空&#xff0c;如果为空的时候是…...

2024年3月 青少年等级考试机器人理论真题二级

202403 青少年等级考试机器人理论真题二级 第 1 题 一个机器小车&#xff0c;用左右两个电机分别控制左右车轮&#xff0c;左侧电机转速是100rpm&#xff0c;右侧电机转速是50rpm&#xff0c;则此机器小车&#xff1f;&#xff08; &#xff09; A&#xff1a;原地右转 B&am…...

C语言学习【printf函数和scanf函数】

C语言学习【printf函数和scanf函数】 printf()函数和scanf()函数可以让用户与程序交流&#xff0c;是输入/输出函数 printf()函数 请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如&#xff0c;打印整数时使用%d&#xff0c;打印字符时使用%c。这些符号被称…...

shell正则表达式

sort命令 以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型来排序 比较原则是从首字符向后&#xff0c;依次按ASCII码值进行比较&#xff0c;最后将他们按升序输出。 sort 对行内容进行升序排序 XXX | sort 选项 sort 选项 文件 常用选项&#x…...

react组件渲染性能优化之函数组件-useCallback使用

useCallback主要就是对函数进行缓存,useCallBack这个Hooks主要是解决React.memo不能缓存事件的问题 useCallBack(fn, dependencies) &#xff1a;fn想要缓存的函数&#xff0c;dependencies有关是否更新 fn 的所有响应式值的一个列表 比如&#xff1a;UseCallBackOptimize组件…...

【C++】:string类的基本使用

目录 引言一&#xff0c;string类对象的常见构造二&#xff0c;string类对象的容量操作三&#xff0c;string类对象的访问及遍历操作四&#xff0c;string类对象的修改操作五&#xff0c;string类非成员函数六&#xff0c;整形与字符串的转换 引言 string 就是我们常说的"…...

多线程的代码案例

目录 单例模式 饿汉模式 懒汉模式 阻塞队列 生产者消费者模型意义: 阻塞队列使用方法 实现阻塞队列 阻塞队列实现生产者消费者模型 定时器 实现简单的定时器 工厂模式 线程池 为啥呢? 从池子里面取 比 创建线程 效率更高 线程池的创建 怎么填坑 ThreadPoolExec…...

什么是Java中的设计模式?请列举几种常见的设计模式

一、引言 在软件开发中&#xff0c;设计模式是解决特定设计问题的最佳实践或通用解决方案。Java作为一种广泛使用的编程语言&#xff0c;其设计模式在软件设计和架构中起着至关重要的作用。设计模式不仅提高了代码的可读性和可维护性&#xff0c;还使得代码更加灵活和可扩展。…...

绘制奇迹:Processing中的动态图形与动画

&#x1f680; 欢迎回到Processing的世界&#xff0c;你的艺术编程航程刚刚开始。在我们的入门篇中&#xff0c;你已经学会了如何用Processing绘制基本的静态图形。现在&#xff0c;让我们一起探索Processing强大的动态图形和动画功能&#xff0c;释放你的创造力&#xff0c;走…...

Django视图Views

Views视图 HttpRequest 和HttpResponse Django中的视图主要用来接受web请求&#xff0c;并做出响应。视图的本质就是一个Python中的函数视图的响应分为两大类 1)以Json数据形式返回(JsonResponse) 2)以网页的形式返回 2.1)重定向到另一个网页 (HttpRe…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

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…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

轻量级Docker管理工具Docker Switchboard

简介 什么是 Docker Switchboard &#xff1f; Docker Switchboard 是一个轻量级的 Web 应用程序&#xff0c;用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器&#xff0c;使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...