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

C++ 运算符重载为非成员函数

运算符也可与重载为非成员函数。这时运算所需要的操作数都需要通过函数的形参表来传递,在形参表中形参从左到右的顺序就是运算符操作数的顺序。如果需要访问运算符参数对象的私有成员,可以将该函数声明为友元函数。

【提示】不用机械地将重载运算符的非成员函数声明为类的友元函数,仅在需要访问类的私有成员或保护成员时再这样做。如果不将其声明为友元函数,该函数仅依赖于类的接口,只要类的接口不变化,该函数的实现就无须变化;如果将其声明为友元函数,该函数会依赖于类的实现,即使类的接口不变化,只要类的私有数据成员的设置发生了变化,该函数的实现就需要变化。

对于双目运算符B,如果要实现b1 B b2,其中b1和b2中只要有一个具有自定义类型,就可以将B重载为非成员函数,函数的形参为b1和b2。 经过重载后,表达式b1 B b2相当于函数调用operator B(b1,b2)

对于前置单目运算符U,如“-”负号等,如果要实现表达式U b,其中b具有自定义类型,就可以将U重载为非成员函数,函数的形参为b。 经过重载后,表达式U b相当于函数调用operator U(b)

对于后置单目运算符++和–,如果要实现表达式b++或b–,其中b为自定义类型,那么运算符就可以重载为非成员函数。这时函数的形参有两个,一个是b,另一个是int型形参。 第二个参数是用于与前置运算符重载函数相区别的。重载之后,表达式b++b--就相当于函数调用operator++(b,0)operator--(b,0)

【例】以非成员函数形式重载Complex的加减法运算和“<<”运算符

将运算符“+”,“-”重载为非成员函数,并将其声明为友元函数,使之实现复数的加减法。重载运算符“<<”可以对cout使用“<<”操作符来输出一个Complex对象,使输出变得更加方便和直观。

//将加减运算符重载为非成员函数
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& c3, const Complex& c4);friend ostream& operator<<(ostream& out, const Complex& c);void display() const;
private:double real;double imag;
};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);
}ostream& operator<<(ostream& out, const Complex& c)
{out << "(" << c.real << "," << c.imag << ")" << endl;return out;
}int main()
{Complex c1(5, 4);Complex c2(2, 10);Complex c3;cout << "c1=" << c1 << endl;	cout << "c2=" << c2 << endl;c3 = c1 + c2;cout << "c3=c1+c2=" << c3 << endl;Complex c4;c4 = operator-(c2,c1);cout << "c4=c2-c1=" << c4 << endl;Complex c5;c5 = 5.0 + c1;cout << "c5=5.0+c1=" << c5 << endl;return 0;
}

运行结果:
在这里插入图片描述

分析:
将运算符重载为类的非成员函数,就必须把操作数都通过形参的方式传递给运算符重载函数。因为将运算符重载为类的非成员函数,使它不能访问类的私有成员,所以将非成员运算符重载函数声明为类的友元函数,使它可以访问类中的私有成员,从而对其进行操作。“<<”操作符的左操作数为operator类型的引用,ostream是cout类型的一个基类,右操作数是Complex类型的引用,这样在执行cout<<c1时,就会调用operator<<(cout,c1)。该函数把通过第一个参数传入的ostream对象以引用形式返回,是为了支持形如“cout<<c1<<c2”的连续输出,因为第二个“<<”运算符的左操作数是第一个“<<”运算符的返回结果。

【总结】
使用非成员函数的重载方式的情况:

(1)要重载的操作符的第一个操作数不是可以更改的类型,例如上例中的“<<”运算符的第一个操作数的类型为ostream,是标准库的类型,无法像其中添加成员函数。

(2)以非成员函数形式重载,支持更灵活的类型转换。例如,上述代码中,可以直接使用5.0+c1,因为Complex的构造函数使得实数可以被隐含转换为Complex类型。这样5.0+c1就会以operator+(Complex(5.0),c1)的方式来执行,c1+5.0也一样,从而支持了实数和复数的相加,既方便又直观;而以成员函数重载时,左操作数必须具有Complex类型,不能是实数,因为调用成员函数的目的对象不会被隐含转换,只有右操作数可以为实数,因为有操作数是函数的形参,可以隐含转换。

http://www.lryc.cn/news/114334.html

相关文章:

  • [国产MCU]-BL602开发实例-定时器
  • re学习(29)攻防世界-CatFly(复原反汇编)
  • Android WIFI-概率性不能自连
  • 用Python批量复制文件,方法有9种,方便快捷
  • 《凤凰架构》第一章——服务架构演进史
  • 【iPhone】手机还有容量,拍视频却提示 iPhone 储存空间已满
  • pycharm中opencv库导入 cv2. 无函数提示跳出解决方法
  • week3
  • LeetCode28.找出字符串中第一个匹配项的下标
  • 爬虫009_字符串高级_替换_去空格_分割_取长度_统计字符_间隔插入---python工作笔记028
  • Windows 安装Tensorflow2.1、Pycharm开发环境
  • 【javaScript】数组的常用方法(自用记忆版)
  • 全新二开美化版UI好看的社区源码下载/反编译版
  • Docker 发布一个springboot项目
  • 办公信息系统安全基本技术要求
  • 有效管理IT问题的5个原则
  • 【MongoDB】解决ProxmoxVE下CentOS7虚拟机安装MongoDB6后启动失败的问题
  • MySQL 事务原理:事务概述、隔离级别、MVCC
  • useEffect从入门到入土
  • 第三章 图论 No.6负环之01分数规划与特殊建图方式
  • 九、Spring 声明式事务学习总结
  • ResNet50卷积神经网络输出数据形参分析-笔记
  • uniapp 微信小程序 封装公共的请求js(api版本)
  • 格式化后数据恢复,教你3个实用方法!
  • LaTex使用技巧21:设置中文环境、字体、行间距和页边距
  • 【RabbitMQ】golang客户端教程3——发布订阅(使用fanout交换器)
  • 图像处理学习笔记
  • 87端口无法访问-GoogleChrome非安全端口列表
  • pyautogui 配合 selenium 实现桌面坐标系定位元素坐标,模拟真实鼠标行为
  • c#设计模式-创建型模式 之 工厂模式