解决C++运算符重载时=和+(或-、*、/、后置自增自减)无法连用

news/2024/10/25 15:27:23/

背景题目:
定义有理数类(分母不为0的分数,分子分母均为整数)Rational,实现相应操作符的重
载。
(1)定义私有数据成员:分子int iUp; 分母 int iDown。
(2)定义私有成员函数:void Reduce() 和 int Gcd(int l, int r),分别用于有理数的
约简和求两个整数的最大公约数。其中,在约简时需要求取分子与分母的最大公约数。
(3)定义构造函数,在构造函数体内可调用Reduce对有理数进行约简。
(4)将负号-和赋值运算符=重载为公有成员函数,分别用于求有理数的负数和赋值。
(5)将前置++、前置–、后置++、后置–重载为公有成员函数,实现有理数自增1或自减
1。
(6)将+、-、*、/重载为友员函数,实现有理数的加减乘除。
(7)将<、<=、>、>=重载为友员函数,实现有理数的大小关系比较。
(8)重载流插入符<<和流提取符>>,分别用于有理数的输出和输入。其中,输出格式为
“分子/分母”,若为整数,则直接输出整数。
为便于说明,此处只给出部分代码:

#include<iostream>using namespace std;class Rational
{
private:	int iUp;int iDown;void Reduce(){...}int Gcd(int l, int r){...}public:Rational(){}Rational(int u, int d){...}Rational& operator=(Rational& r){iUp=r.iUp;iDown = r.iDown;Reduce();return *this;}Rational operator-(){Rational temp;temp.iUp = -iUp;temp.iDown = iDown;return temp;}Rational& operator++(){iUp += iDown;Reduce();return *this;}Rational operator++(int){Rational temp = *this;iUp += iDown;Reduce();return temp;}Rational& operator--(){iUp -= iDown;Reduce();return *this;}Rational operator--(int){Rational temp = *this;iUp -= iDown;Reduce();return temp;}friend Rational operator+(const Rational& a, const Rational& b);friend Rational operator-(const Rational& a, const Rational& b);friend Rational operator*(const Rational& a, const Rational& b);friend Rational operator/(const Rational& a, const Rational& b);friend bool operator<(const Rational& a, const Rational& b);friend bool operator<=(const Rational& a, const Rational& b);friend bool operator>(const Rational& a, const Rational& b);friend bool operator>=(const Rational& a, const Rational& b);friend istream& operator>>(istream& in, Rational& r);friend ostream& operator<<(ostream& out, const Rational& r);
};Rational operator+(const Rational& a, const Rational& b)
{Rational temp;temp.iUp = a.iUp * b.iDown + b.iUp * a.iDown;temp.iDown = a.iDown * b.iDown;temp.Reduce();return temp;
}
Rational operator-(const Rational& a, const Rational& b)
{Rational temp;temp.iUp = a.iUp * b.iDown - b.iUp * a.iDown;temp.iDown = a.iDown * b.iDown;temp.Reduce();return temp;
}
Rational operator*(const Rational& a, const Rational& b)
{Rational temp;temp.iUp = a.iUp * b.iUp;temp.iDown = a.iDown * b.iDown;temp.Reduce();return temp;
}
Rational operator/(const Rational& a, const Rational& b)
{Rational temp;temp.iUp = a.iUp * b.iDown;temp.iDown = a.iDown * b.iUp;temp.Reduce();return temp;
}bool operator<(const Rational& a, const Rational& b)
{...
}
bool operator<=(const Rational& a, const Rational& b)
{...
}
bool operator>(const Rational& a, const Rational& b)
{...
}
bool operator>=(const Rational& a, const Rational& b)
{...
}istream& operator>>(istream& in, Rational& r)
{...
}
ostream& operator<<(ostream& out, const Rational& r)
{...
}int main()
{int up, down;cin >> up >> down;Rational a(up, down);cin >> up >> down;Rational b(up, down);Rational c;c = a + b;cout << "a+b: " << c;c = a - b;cout << "a-b: " << c;c = a * b;cout << "a*b: " << c;c = a / b;cout << "a/b: " << c;c = -a;cout << "-a: " << c;c = ++a;cout << "++a: " << c;c = --a;cout << "--a: " << c;c = a++;cout << "a++: " << c;c = a--;cout << "a--: " << c;...return 0;
}

欲运行代码,结果报错:
在这里插入图片描述可以看到等号与+、-、*、/、后置自增、后置自减连用的地方,都标红,报错信息为“error C2679: 二进制“=”: 没有找到接受’Rational’类型的右操作数的运算符(或没有可接受的转换)”。
可是赋值运算符已经重载了,为什么这里会没有起作用呢?经过查询,我发现,问题出在重载等号传入的参数和其他运算符的返回值类型上。
源码中重载等号的参数类型是Rational&,是一个可变引用

	Rational& operator=(Rational& r){iUp=r.iUp;iDown = r.iDown;Reduce();return *this;}

重载+、-、*、/、后置自增、后置自减的返回参数均为Rational,是一个临时局部变量。

Rational operator+(const Rational& a, const Rational& b)
{Rational temp;temp.iUp = a.iUp * b.iDown + b.iUp * a.iDown;temp.iDown = a.iDown * b.iDown;temp.Reduce();return temp;

在C++里,临时局部变量没有合法内存空间,是不可以转为可变引用的,因为可变引用需要有合法的内存空间。但是常量引用可以接收这一类没有有效内存空间的值,即const Rational&。
于是我将重载等号代码修改,

	Rational& operator=(const Rational& r){iUp=r.iUp;iDown = r.iDown;Reduce();return *this;}

问题就解决了。
在这里插入图片描述接下来讲一下常量引用的原理,以整型常量引用为例:

int &a=10;//会报错,10没有申请合法内存空间
const int &a=10;//不会报错//编译器会自动将代码优化为int temp=10;//const int &a=temp;

总结:
当不涉及修改数据操作时,传递参数最好用常量引用的形式,即const type&,因为这个方式是适应性最高的,可以接收有合法内存空间的变量或常量,也可以接收没有事先申请合法内存空间的临时(局部)变量或常量,还可以保护数据,防止误操作。


http://www.ppmy.cn/news/315261.html

相关文章

shell脚本实现俄罗斯方块

脚本内容&#xff1a; #!/bin/bash # Tetris Game# 10.21.2003 xhchen< [email]xhchenwinbond.com.tw[/email]> #APP declarationAPP_NAME"${0##*[\\/]}"APP_VERSION"1.0" #颜色定义cRed1cGreen2cYellow3cBlue4cFuchsia5cCyan6cWhite7colorTable($c…

特殊矩阵的压缩存储(对称矩阵,三角矩阵,对角矩阵,稀疏矩阵的顺序,链序存储,十字链表的建立)

特殊矩阵的压缩存储 压缩存储的定义&#xff1a; 若多个数据元素的值都相同&#xff0c;则只分配一个元素值的存储空间&#xff0c;且 零元素不占存储空间。 能够压缩的一些矩阵&#xff1a; 一些特殊矩阵&#xff0c;如&#xff1a;对称矩阵&#xff0c;对角矩阵&#xff0c;…

稀疏矩阵转十字链表

定义: 十字链表(Orthogonal List)是有向图的另一种链式存储结构。该结构可以看成是将有向图的邻接表和逆邻接表结合起来得到的。用十字链表来存储有向图&#xff0c;可以达到高效的存取效果。同时&#xff0c;代码的可读性也会得到提升。 ● 特点 • 只保存非零值 • 为每一行设…

shell脚本的俄罗斯方块 : )

#!/bin/bash # Tetris Game # 10.21.2003 xhchen<[email]xhchenwinbond .com.tw[/email]> #APP declaration APP_NAME"${0##*[\\/]}" APP_VERSION"1.0" #颜色定义 cRed1 cGreen2 cYellow3 cBlue4 cFuchsia5 cCyan6 cWhite7 colorTable($cRed $cGre…

栈、队列和数组(包括求解迷宫问题)

1.1 琐碎知识点 栈、队列、数组是线性存储结构&#xff0c;它们都是一段连续的内存空间&#xff0c;其中栈和队列是动态的&#xff0c;而数组是静态的。它们的区别在于&#xff1a; 栈&#xff1a;后进先出&#xff0c;只能在栈顶进行插入和删除操作。队列&#xff1a;先进先出…

西农大 C plus

问题 K: oop实习-11.运算符重载 题目描述 定义有理数类&#xff08;分母不为0的分数&#xff0c;分子分母均为整数&#xff09;Rational&#xff0c;实现相应操作符的重载。 &#xff08;1&#xff09;定义私有数据成员&#xff1a;分子int iUp; 分母 int iDown。 &#xff08…

程序员面试题精选100题(51)-顺时针打印矩阵

// 程序员面试题精选100题(51)-顺时针打印矩阵.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <iostream> using namespace std; #define M 9 #define N 4 int _tmain(int argc, _TCHAR* argv[]) {int arr[M][N];int all0;int i,j,iup0,…

运算符重载例题

用的是vs2019编译器 这是一个有关运算符重载的例题&#xff0c;希望大家作以参考 定义有理数类&#xff08;分母不为0的分数&#xff0c;分子分母均为整数&#xff09;Rational&#xff0c;实现相应操作符的重载。 &#xff08;1&#xff09;定义私有数据成员&#xff1a;分子…