面向对象程序设计|理解++i和i++

news2024/11/19 23:34:15

首先我们从最简单的整型运算来理解前++和后++:

 将a=10再赋值20意味着(a=10)返回的是a的空间,又把这个20赋值给这个空间的内存,最后a=20;

++(++a)意味着++a返回的是空间(引用),可以继续作++的调用,引用使得++a是可修改的左值;

又由于后置++的优先级大于前置++,因此20行和21行的本质一样,会出现报错。因为a++操作通过临时量返回其值,该值是一个常量,因此不能被修改(不是左值),而后缀++需要对左值进行操作,所以会引起编译错误。
所谓的左值,说通俗一点就是可以被修改和引用的值,左值可以取地址。与之相对的就是右值。在使用时,左值可以作为右值,但右值不能作为左值。

以两道例题为例:

题目一:X的放大与缩小(运算符重载)

题目描述:

X字母可以放大和缩小,变为n行X(n=1,3,5,7,9,...,21)。例如,3行x图案如下:

现假设一个n行(n>0,奇数)X图案,遥控器可以控制X图案的放大与缩小。遥控器有5个按键,1)show,显示当前X图案;2)show++, 显示当前X图案,再放大图案,n+2;3)++show,先放大图案,n+2,再显示图案;4)show--,显示当前X图案,再缩小图案,n-2;5)--show,先缩小图案,n-2,再显示图案。假设X图案的放大和缩小在1-21之间。n=1时,缩小不起作用,n=21时,放大不起作用。

用类CXGraph表示X图案及其放大、缩小、显示。主函数模拟遥控器,代码如下,不可修改。请补充CXGraph类的定义和实现。

 输入要求:

第一行n,大于0的奇数,X图案的初始大小。

第二行,操作次数

每个操作一行,为show、show++、show--、--show、++show之一,具体操作含义见题目。

输出要求:

对每个操作,输出对应的X图案。

输入样例:

3
5
show
show++
show++
++show
--show

输出样例:

XXX
 X
XXX
 
XXX
 X
XXX
 
XXXXX
 XXX
  X
 XXX
XXXXX
 
XXXXXXXXX
 XXXXXXX
  XXXXX
   XXX
    X
   XXX
  XXXXX
 XXXXXXX
XXXXXXXXX
 
XXXXXXX
 XXXXX
  XXX
   X
  XXX
 XXXXX
XXXXXXX

代码示例:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;
 
class XGraph
{
private:
	int n;
public:
	XGraph(int nn) :n(nn) {}
	XGraph(XGraph& rhs)
	{
		n = rhs.n;
	}
	XGraph& operator++()//前置++,返回的是引用;前置用引用则是为了不产生临时变量,可以减少内存的消耗。
	{
		if (this->n <= 19)
		{
			this->n += 2;
		}
		return *this;
	}
	XGraph operator++(int)//后置++,返回的是临时对象,因为后置的时候原来的对象已经被++改变了。
	{					  //后置的函数的声明里面参数列表中比前置多了一个int,这里的int其实是作为区分前后置的标志,在函数体里面并没有直接地用到。
		XGraph temp = *this;
		if (this->n <= 19)
		{
			this->n += 2;
		}
		return temp;
	}
	XGraph& operator--()//原理与++或--相同
	{
		if (this->n >= 3)
		{
			this->n -= 2;
		}
		return *this;
	}
	XGraph operator--(int)
	{
		XGraph temp = *this;
		if (this->n >= 3)
		{
			this->n -= 2;
		}
		return temp;
	}
	friend ostream& operator<<(ostream& out, const XGraph& rhs);//输出运算符重载,记住特定的格式
};
 
ostream& operator<<(ostream& out, const XGraph& rhs)
{
	for (int i = 0; i < (rhs.n + 1) / 2; i++)
	{
		for (int j = 0; j < i; j++)
		{
			cout << " ";
		}
		for (int j = i; j < rhs.n - i; j++)
		{
			cout << "X";
		}
		cout << endl;
	}
	for (int i = (rhs.n + 1) / 2; i < rhs.n; i++)
	{
		for (int j = rhs.n - 1 - i; j > 0; j--)
		{
			cout << " ";
		}
		for (int j = rhs.n - 1 - i; j <= i; j++)
		{
			cout << "X";
		}
		cout << endl;
	}
	return out;
}
 
 
int main()
{
	int t, n;
	string command;
	cin >> n;
	XGraph xGraph(n);
	cin >> t;
	while (t--)
	{
		cin >> command;
		if (command == "show++")
		{
			cout << xGraph++ << endl;
		}
		else if (command == "++show")
		{
			cout << ++xGraph << endl;
		}
		else if (command == "show--")
		{
			cout << xGraph-- << endl;
		}
		else if (command == "--show")
		{
			cout << --xGraph << endl;
		}
		else if (command == "show")
			cout << xGraph << endl;
 
	}
	return 0;
}

前置++,返回的是引用;前置用引用则是为了不产生临时变量,可以减少内存的消耗。

后置++,返回的是临时对象,因为后置的时候原来的对象已经被++改变了。

后置的函数的声明里面参数列表中比前置多了一个int,这里的int其实是作为区分前后置的标志,在函数体里面并没有直接地用到。

再以整数运算为例,如果是 cout << a++; 的话,是先输出a的值,a再加1。当运行后置++的时候,我们先备份当前对象的值,然后在返回前把它做了加一的动作,然后返回备份的值。因为备份的值是局部对象,因此不能返回局部对象的引用,引用的话就是说你出了这个函数,空间必须还在,但局部对象在函数结束后就被析构了,所以只能返回对象。

题目二:三维点坐标平移(增量运算符重载)

题目描述:

定义一个三维点Point类,利用友元函数重载"++"和"--"运算符,并区分这两种运算符的前置和后置运算。

++表示x\y\z坐标都+1,--表示x\y\z坐标都-1

请完成以下程序填空

输入要求:

只有一行输入,输入三个整数,表示点的x/y/z坐标

输出要求:

由主函数自行输出

输入样例:

10 20 30

输出样例:

x=11 y=21 z=31
x=10 y=20 z=30
x=11 y=21 z=31
x=11 y=21 z=31
x=9 y=19 z=29
x=10 y=20 z=30
x=9 y=19 z=29
x=9 y=19 z=29

代码框架:

#include <iostream>
using namespace std;

class Point;
Point operator -- (Point & );
Point operator -- (Point &, int);

class Point {
private:
	int x, y, z;
public:
	Point(int tx=0, int ty=0, int tz=0 )
	{	x = tx, y = ty, z = tz;	}
	Point operator ++ ();
	Point operator ++ (int);
	friend Point operator -- (Point & );
	friend Point operator -- (Point &, int);
	void print();
};
//完成以下填空
/********** Write your code here! **********/




/*******************************************/
int main()
{	int tx, ty, tz;
	cin>>tx>>ty>>tz;
	Point p0(tx, ty, tz); //原值保存在p0
	Point p1, p2;	//临时赋值进行增量运算

	//第1行输出
	p1 = p0;
	p1++;;
	p1.print();
	//第2行输出
	p1 = p0;
	p2 = p1++;
	p2.print();
	//第3、4行输出,前置++
	p1 = p0;
	(++p1).print();
	p1.print();
	//第5、6行输出,后置--
	p1 = p0;
	p1--;
	p1.print();
	p0.print();
	//第7、8行输出,前置--
	p1 = p0;
	(--p1).print();
	p1.print();

	return 0;
}

代码示例:

#include <iostream>
using namespace std;

class Point;
Point operator -- (Point & );
Point operator -- (Point &, int);

class Point {
private:
	int x, y, z;
public:
	Point(int tx=0, int ty=0, int tz=0 )
	{	x = tx, y = ty, z = tz;	}
	Point operator ++ ();
	Point operator ++ (int);
	friend Point operator -- (Point & );
	friend Point operator -- (Point &, int);
	void print();
};
//完成以下填空
Point Point::operator++()
{
	x++;
	y++;
	z++;
	return *this;
}

Point Point::operator++(int)
{
	Point temp = *this;
	x++;
	y++;
	z++;
	return temp;
}
Point operator -- (Point& rhs)
{

	rhs.x--;
	rhs.y--;
	rhs.z--;
	return rhs;
}
Point operator -- (Point& rhs, int n)
{
	Point temp = rhs;
	rhs.x--;
	rhs.y--;
	rhs.z--;
	return temp;
}

void Point::print()
{
	cout << "x=" << x << " y=" << y << " z=" << z << endl;
}
int main()
{	int tx, ty, tz;
	cin>>tx>>ty>>tz;
	Point p0(tx, ty, tz); //原值保存在p0
	Point p1, p2;	//临时赋值进行增量运算

	//第1行输出
	p1 = p0;
	p1++;;
	p1.print();
	//第2行输出
	p1 = p0;
	p2 = p1++;
	p2.print();
	//第3、4行输出,前置++
	p1 = p0;
	(++p1).print();
	p1.print();
	//第5、6行输出,后置--
	p1 = p0;
	p1--;
	p1.print();
	p0.print();
	//第7、8行输出,前置--
	p1 = p0;
	(--p1).print();
	p1.print();

	return 0;
}

我们按照要求完成代码,同时用另一种方法完成代码,分别成为代码一、代码二。

代码二:

#include <iostream>
using namespace std;

class Point;

class Point {
private:
	int x, y, z;
public:
	Point(int tx = 0, int ty = 0, int tz = 0)
	{
		x = tx, y = ty, z = tz;
	}
	Point& operator ++ ();
	Point operator ++ (int);
	Point& operator -- ();
	Point operator -- (int);
	void print();
};
//完成以下填空
Point& Point::operator++()
{
	x++;
	y++;
	z++;
	return *this;
}

Point Point::operator++(int)
{
	Point temp = *this;
	x++;
	y++;
	z++;
	return temp;
}
Point& Point::operator -- ()
{

	x--;
	y--;
	z--;
	return *this;
}
Point Point::operator -- (int)
{
	Point temp = *this;
	x--;
	y--;
	z--;
	return temp;
}

void Point::print()
{
	cout << "x=" << x << " y=" << y << " z=" << z << endl;
}
int main()
{
	int tx, ty, tz;
	cin >> tx >> ty >> tz;
	Point p0(tx, ty, tz); //原值保存在p0
	Point p1, p2;	//临时赋值进行增量运算

	//第1行输出
	p1 = p0;
	p1++;;
	p1.print();
	//第2行输出
	p1 = p0;
	p2 = p1++;
	p2.print();
	//第3、4行输出,前置++
	p1 = p0;
	(++p1).print();
	p1.print();
	//第5、6行输出,后置--
	p1 = p0;
	p1--;
	p1.print();
	p0.print();
	//第7、8行输出,前置--
	p1 = p0;
	(--p1).print();
	p1.print();


	return 0;
}

我们会发现对代码一,有这样的错误:

 而代码二则不会产生问题:

其本质原因是:代码一第一个前--返回的是对象,再次前--,是在临时对象上减而不是在原对象,返回对象做对象的备份和原对象不是一个空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/669672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java版本工程项目管理系统源码

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

STM32存储器映射

STM32的寻址范围 32位的单片机有32根地址线&#xff08;每根地址线有两种状态&#xff1a;导通或者不导通&#xff09;。 单片机内存地址访问的存储单元是按字节编址的。 存储器映射 存储器指可以存储数据的设备&#xff0c;本身没有地址信息&#xff0c;对存储器分配地址…

JAVA_HOME变量的详细配置(图文)

用到Java项目的时候&#xff0c;有时候要用到Java_home&#xff0c;这个需要在系统配置中配置一下。如何操作呢&#xff1f;以下为详细的图文步骤。 1&#xff09;打开环境变量的窗口 2&#xff09;打开新建系统变量 3&#xff09;编辑JAVA_HOME 在变量名后输入JAVA_HOME,找到…

IDEA配置本地Maven详细教程

IDEA配置本地Maven详细教程 一、下载二、安装三、配置环境变量四、IDEA配置Maven 一、下载 官网下载&#xff1a;点击下载 网盘下载&#xff1a;点击下载 二、安装 将下载后的zip文件&#xff08;免安装版&#xff09;解压到自己想要放的位置&#xff0c;&#xff0c;我这里…

第八十一天学习记录:gVim的使用

首先&#xff0c;根据所使用的系统下载VIM&#xff0c;百度搜索或者CSDN搜索有资源可以下载。 gVim是Windows下的一个Vim实现&#xff0c;它提供了类似于Vim命令行界面的编辑器视窗&#xff0c;并且支持通过鼠标和菜单来执行一些基本的编辑命令。 安装完成后&#xff0c;桌面上…

Video-LLaMa:利用多模态增强对视频内容理解

在数字时代&#xff0c;视频已经成为一种主要的内容形式。但是理解和解释视频内容是一项复杂的任务&#xff0c;不仅需要视觉和听觉信号的整合&#xff0c;还需要处理上下文的时间序列的能力。本文将重点介绍称为video - llama的多模态框架。Video-LLaMA旨在使LLM能够理解视频中…

软考A计划-系统集成项目管理工程师-信息化系统的生命周期-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

【GESP】2023年03月图形化一级 -- 问路

文章目录 问路1. 准备工作2. 功能实现3. 设计思路与实现&#xff08;1&#xff09;角色、舞台背景设置a. 角色设置b. 舞台背景设置 &#xff08;2&#xff09;脚本编写a. 角色&#xff1a;Averyb. 角色&#xff1a;Dee 4. 评分标准 问路 1. 准备工作 &#xff08;1&#xff09…

全网超详细的【Axure】Axure RP 10 的下载、安装、中文字体、免授权

文章目录 1. 文章引言2. axure10的安装3. axure10的元件库4. axure10的下载地址 1. 文章引言 最近在学习原型图&#xff0c;针对画原型图的工具&#xff0c;反复对比墨刀、Axure、xiaopiu后&#xff0c;最终选择了Axure。 接下来&#xff0c;我便详细介绍如何安装axure10&…

将模型从 PyTorch 导出到 ONNX 并使用 ONNX 运行时运行它

将模型从 PyTorch 导出到 ONNX 并使用 ONNX 运行时运行它&#xff08;可选&#xff09; 在本教程中&#xff0c;我们描述了如何将 PyTorch 中定义的模型转换为 ONNX 格式&#xff0c;然后在 ONNX 运行时中运行它。 ONNX 运行时是针对 ONNX 模型的以性能为中心的引擎&#xff…

微服务简介,Springcloud-alibaba中的Nacos简介

目录 一&#xff1a;微服务架构 1.0&#xff1a;单体架构 1.1&#xff1a;微服务架构 1.2&#xff1a;微服务架构的优势 1.3&#xff1a;微服务架构的缺点(挑战) 1.4&#xff1a;SpringCloud与微服务关系 1.5&#xff1a;SpringBoot和SpringCloud关系 二&#xff1a;服务…

RabbitMQ下载与安装

RabbitMQ下载与安装 想要使用RabbitMQ首先要有Erlang/OTP的运行环境&#xff0c;也就是说首先要下载erlang 在下载Erlang/OTP之前&#xff0c;需要弄清楚RabbitMQ和ErLang之间的版本对应关系。 The table below provides an Erlang compatibility matrix of currently suppo…

用html5、css3和一些简单的js代码写了一个个人网站,之后如何上线?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言网站上线方案1 Git…

跨境电商怎么做?如何选品及销售?

跨境电商是指在不同国家和地区之间进行的电子商务交易活动。它的出现极大地促进了国际贸易和跨境交流。对于个人来说&#xff0c;通过跨境电商可以更加方便地购买到国外的优质商品&#xff0c;也可以将自己的产品推向全球市场。但是&#xff0c;对于大多数人来说&#xff0c;跨…

一文搞定Shell编程中的单引号、双引号、反引号和转义符的区别和使用

前言 Shell编程中&#xff0c;不仅会是使用变量&#xff0c;还经常会使用$、\、单引号、双引号、反引号等符号。 这些符号在使用中&#xff0c;有时候难免混乱&#xff0c;所以整理此文&#xff0c;便于学习&#xff0c;希望对你有用 文章目录 前言一. 符号的介绍与对比二. 单…

复习html的第二章

什么是 HTML&#xff1f; HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言 (Hyper Text Markup Language)HTML 不是一种编程语言&#xff0c;而是一种标记语言 (markup language)标记语言是一套标记标签 (markup tag)HTML 使用标记标签来描述网页 HTML 标签 HT…

ECC加密算法详解+python实现

一.前言 目前比较受欢迎的加密算法一共存在两种&#xff0c;一种是基于大整数因子分解问题&#xff08;IFP&#xff09;的RSA算法和基于椭圆曲线上离散对数计算问题&#xff08;ECDLP&#xff09;的ECC算法。之前对RSA算法进行过很详细的讲解&#xff0c;但是ECC加密算法还没有…

科普文章:会议论文VS期刊论文,两者有何区别?学界的认可度两者一致吗?

文章目录 一、会议论文和期刊论文的概念1.1 会议论文1.2 期刊论文1.3 总结 二、不同之处2.1 内容的不同2.2 审稿周期的不同2.3 认可度的区别 三、投稿的一些建议四、自己的一点小想法 计算机深度学习方向研一学生一枚&#xff0c;论文才有想法&#xff0c;下一步打算开始写了&a…

业务流程绕过测试-业务安全测试实操(18)

业务流程绕过测试,业务上限测试 业务流程绕过测试 测试原理和方法 该项测试主要针对业务流程的处理流程是否正常,确保攻击者无法通过技术手段绕过某些重要流程步骤,检验办理业务过程中是否有控制机制来保证其遵循正常流程。例如业务流程分为三步:第一步,注册并发送验证码:…

JS 循环链表

文章目录 导文循环链表的概念循环链表具有以下几个特点&#xff1a;实现一个循环列表 导文 循环链表是一种特殊的链表数据结构&#xff0c;其中最后一个节点指向链表的头节点&#xff0c;形成一个循环的环状结构。与普通链表不同&#xff0c;循环链表没有明确的结束点&#xff…