运算符重载

一.运算符重载基本规则

1.运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。

2.一般来讲,重载的功能应当与原有功能相似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。

3.运算符的重载形式有两种,分别是重载为类的非静态成员和重载为非成员函数,下面我们也将从两种下手开始讨论。

它们的一般语法形式为:

返回类型 operator 运算符(形参表)
{

函数体

}

注:返回类型指定了重载运算符的返回类型,也就是运算结果类型。

二.加减法重载

说明:重载为类的成员函数时,第一个操作数会被作为函数调用的目的对象,因此无法出现在参数表中。即oprd1 B oprd2,其中oprd1为A类的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型,即oprd1 B oprd2相当于oprd1.operator B(oprd2)

(一).加减法重载为成员函数


#include "pch.h"
#include <iostream> using namespace std; class Complex
{
public:
Complex(double r=0.0,double i=0.0):real(r),imag(i){}
Complex operator+(const Complex &c2)const;
Complex operator-(const Complex &c2)const;//用对象作为参数时,用引用或者传地址,一般用引用
void display()const
{
cout << "(" << real << "," << imag << ")" << endl;
}
private:
double imag, real;//复数的虚部和实部
}; Complex Complex::operator+(const Complex &c2)const
{
return Complex(real + c2.real, imag + c2.imag);//创建了一个临时无名对象作为返回值
} Complex Complex::operator-(const Complex &c2)const
{
return Complex(real - c2.real, imag - c2.imag);//创建了一个临时无名对象作为返回值
} int main()
{
Complex c1(5, 4), c2(2, 3), c3;
cout << "c1="; c1.display();
cout << "c2="; c2.display();
c3 = c1 + c2;
cout << "c3=c1+c2="; c3.display();
c3 = c1 - c2;
cout << "c3=c1-c2="; c3.display();
return 0;
}

运行结果:

  • 修改1:由上面写的说明,我们来对说明进行证明,我们修改代码如图

我们运行可以正常运行,证明了我们上面的说明。

  • 修改2:我们定义一个新的Complex类型的c,对它进行以下操作

注:这里我们看到整数5加到了原来c1的5上,可能有的人会想为什么不在c1的4上也加上,这里我们需要理解一下复数(a+bi)+(c+di)=(a+c)+(b+d)i。

当我们加上5的时候相当于让实部为5,让虚部为0了即让d为0了。

  • 修改3:

我们发现也是正确的,那如果我们把它写成c=5+c1又会不会对呢?

  • 修改4:

我们发现程序报错,说明这样是不对的,那我们怎样解决它呢?这里就需要我们把运算符重载为非成员函数了。那这又是为什么呢?

(二).加减法重载为非成员函数


#include "pch.h"
#include <iostream> using namespace std; class Complex
{
public:
Complex(double r=0.0,double i=0.0):real(r),imag(i){}
friend Complex operator+(const Complex &c1,const Complex &c2);
friend Complex operator-(const Complex &c1,const Complex &c2);//用对象作为参数时,用引用或者传地址,一般用引用
void display()
{
cout << "(" << real << "," << imag << ")" << endl;
}
private:
double imag, real;
}; Complex operator+(const Complex &c1, const Complex &c2)
{
return Complex(c1.real + c2.real, c1.imag + c2.imag);//创建了一个临时无名对象作为返回值
} Complex operator-(const Complex &c1, const Complex &c2)
{
return Complex(c1.real - c2.real, c1.imag - c2.imag);//创建了一个临时无名对象作为返回值
} int main()
{
Complex c1(5, 4), c2(2, 3), c3,c;
cout << "c1="; c1.display();
cout << "c2="; c2.display(); c3 = c1 + c2;
cout << "c3=c1+c2="; c3.display();
c3 = c1 - c2;
cout << "c3=c1-c2="; c3.display(); c =5+ c1 ;
cout << "c=c1+5="; c.display(); return 0;
}

运行截图:

我们注意看这里就实现了c=5+c1。

那我们思考为什么以非成员函数形式重载,就可以实现c=5+c1呢?

(教材的315页对此进行了详细解释)因为Comlpex的构造函数使得实数可以隐含转换为Complex类型,而以成员函数重载的时候,左操作数是调用成员函数的目的对象,它不会被隐含转化,只有右操作数是函数的参数,可以隐含转化为Complex类型。

三.“++”的重载

(一)“++”的重载为成员函数

#include "pch.h"
#include <iostream> using namespace std; class Complex
{
public:
Complex(double r=0.0,double i=0.0):real(r),imag(i){}
Complex &operator++();
Complex operator++(int);//后++
void display()
{
cout << "(" << real << "," << imag << ")" << endl;
}
private:
double imag, real;
}; Complex &Complex::operator++()
{
imag++;
real++;//先++
return *this;
} Complex Complex::operator++(int)
{
Complex a = *this;//this指向的原来的对象,先把自己的值弄出来,在对自己++
++(*this);
return a;
} int main()
{
Complex a(1, 2),b,d;
a.display(); b = ++a;
cout << "++a="; b.display();
d = a++;
cout << "a++="; d.display(); cout << "a++后"; a.display(); return 0;
}

运行截图:

这里我们注意看先++和后++的区别,在代码的最后我们也可以看到,后++的实现。

(二)“++”的重载为非成员函数


#include "pch.h"
#include <iostream> using namespace std; class Complex
{
public:
Complex(double r=0.0,double i=0.0):real(r),imag(i){} friend Complex operator++(Complex &c);//前++
friend Complex operator++(Complex &c,int);//后++ void display()
{
cout << "(" << real << "," << imag << ")" << endl;
}
private:
double imag, real;
}; Complex operator++(Complex &c)//前++
{
c.imag++;
c.real++;
return c;
} Complex operator++(Complex &c,int)//后++
{
Complex a = c;
++c;
return a;
} int main()
{
Complex a(1, 2),b,d;
a.display(); b = ++a;
cout << "++a="; b.display();
d = a++;
cout << "a++="; d.display(); cout << "a++后"; a.display(); return 0;
}

运行截图:

这里我们注意我们是通过传值的方式传递参数的,假如我们进行如下的修改

  • 修改1:

运行结果:

我们观察运行结果发现出现了错误,原因是这个函数的形参是对象,是通过传值的方式传递参数的,函数体内对形参的所有修改都无法传到函数体的外面。而形参是对象的引用时,是通过传地址的方式传递参数的。

c++第五次作业的更多相关文章

  1. 耿丹CS16-2班第五次作业汇总

    Deadline: 2016-10-26 23:59 作业内容 实验4-1 求1到20的阶乘的和,其中求阶乘用函数完成. 实验4-2 写一个判素数的函数,在主函数输入一个整数,输出其是否是素数的信息. ...

  2. C 语言学习 第五次作业总结

    第五次作业,主要学习和复习的是几种循环结构的使用. 在前一次的课堂上,同学们已经学习了分支语句的使用.分支语句和循环语句配合使用,就可以写出更多的,逻辑功能丰富的代码了. 逻辑功能的丰富,也意味着学习 ...

  3. C语言第五次作业——循环结构

    C语言程序设计第五次作业--循环结构(1) (一)改错题 输出华氏摄氏温度转换表:输入两个整数lower和upper,输出一张华氏摄氏温度转换表,华氏温度的取值范围是{lower,upper},每次增 ...

  4. 17秋 软件工程 团队第五次作业 Alpha

    题目:团队作业--Alpha冲刺 17秋 软件工程 团队第五次作业 Alpha 12次Scrum 第一次Scrum 第二次Scrum 第三次Scrum 第四次Scrum 第五次Scrum 第六次Scr ...

  5. C语言基础课第五次作业

    PTA第五次作业 7-2 统计一行文本中的单词个数 一.程序代码 #include<stdio.h> int main(void) { ]; ,word=; char c; gets(st ...

  6. 17秋 软件工程 团队第五次作业 Alpha Scrum1

    题目:团队作业--Alpha冲刺 17秋 软件工程 团队第五次作业 Alpha Scrum1 各个成员在 Alpha 阶段认领的任务 伟航:督促和监督团队进度,协调组内合作 港晨:APP前端页面编写: ...

  7. 17秋 软件工程 团队第五次作业 Alpha Scrum2

    17秋 软件工程 团队第五次作业 Alpha Scrum2 今日完成的任务 杰麟:Java后端的学习: 世强:登录和注册接口编写: 港晨:完成数据库表的设计: 树民.陈翔:完成超级管理员后端框架. 其 ...

  8. 17秋 软件工程 团队第五次作业 Alpha Scrum3

    17秋 软件工程 团队第五次作业 Alpha Scrum3 今日完成的任务 杰麟:java后端学习: 世强:Android的部门基础信息模块的信息显示和对接后台: 港晨:后台管理登陆界面ui设计: 树 ...

  9. 17秋 软件工程 团队第五次作业 Alpha Scrum4

    17秋 软件工程 团队第五次作业 Alpha Scrum4 今日完成的任务 世强:部门基础信息模块数据更新.部门审核提交: 港晨:设计编写登录界面的一部分: 树民:学习python基本语法.flask ...

  10. 17秋 软件工程 团队第五次作业 Alpha Scrum5

    17秋 软件工程 团队第五次作业 Alpha Scrum5 今日完成的任务 世强:消息通知管理列表页界面编写,下拉加载效果: 港晨:编写登录界面: 树民: 伟航:学习了flask_restful框架的 ...

随机推荐

  1. HUSTOJ搭建后为了方便作为Judger调用进行的一些修改操作

    这里的操作主要包括: 找到初始的MySQL数据库用户名和密码: 将 csrf 设置为固定值: 取消掉同一用户相邻提交时间间隔需要10秒钟的限制. 内容如下: 系统:ubuntu18.04.2 hust ...

  2. 超好用的K8s诊断工具:kubectl-debug

    在K8s环境部署应用后,经常遇到需要进入pod进行排错.除了查看pod logs和describe方式之外,传统的解决方式是在业务pod基础镜像中提前安装好procps.net-tools.tcpdu ...

  3. java面试 (六)

    1 String.split(String regex), 传入的参数是正则表达式,有一些特殊字符(比如.[]()\| 等)需要转义. 2  关于枚举类型,一般用作常量,理想情况下,枚举中的属性字段是 ...

  4. nginx做正向代理https遇到SSL_do_handshake()握手失败

    SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number) wh ...

  5. appium 弹窗处理

    测试过程中遇到两类弹窗: 系统权限弹窗具体业务弹窗系统权限弹窗Android系统权限弹窗一般出现在安装 app 后首次打开,如:定位权限.电话权限等.我们可以按顺序执行测试用例,将该类操作放到 Ini ...

  6. jenkins自动打tag

    思路: 1.手动输入需要tag的版本号,如“build001”,填写svn有权限的密码(账号默认值),填写打tag的说明 2.脚本根据tag的版本号,自动创建目录(版本号为目录名称) 3.将需要打ta ...

  7. 超简单的react和typescript和引入scss项目搭建流程

    1.首先我们先创建一个react项目,react官网也有react项目搭建的命令 npx create-react-app my-app cd my-app 2.安装我们项目需要的样式依赖,这个项目我 ...

  8. CF1051D Bicolorings

    题目描述 咳咳,懒得复制了上面是两张图:) 解题思路 这题是一道很好的题,感觉之前做过,一开始手推状态找规律,可以用状压但是没想到 借鉴了一下大佬的dp modify数组用以累加新增的状态数 dp数组 ...

  9. 链表习题(8)-寻找单链表中数据域大小为k的结点,并与前一结点交换,如果前一结点存在的情况下

    /*寻找单链表中数据域大小为k的结点,并与前一结点交换,如果前一结点存在的情况下*/ /* 算法思想:定义两个指针,pre指向前驱结点,p指向当前结点,当p->data == k的时候,交换 p ...

  10. Dubbo快速入门 五

    5. Dubbo注解版 之前在dubbo配置文件显式编写内容提供者和消费者,官方还提供了了一种注解方式,接下来改造项目 1.服务提供方 dubbo配置文件 将之前手动申明注释掉,添加<dubbo ...