二元运算符重载

------------------siwuxie095

二元运算符重载

所谓 二元运算符,即 这个符号与两个操作数进行运算

(1)加号 + 的重载

加号 + 的重载方式有两种:一种是友元函数重载,一种是成员函数重载

1)先来看成员函数重载,如下:

定义一个坐标类:Coordinate

在类中声明成员函数 operator+(),它的参数是 const Coordinate &coor

在实现时:

首先需要定义一个临时对象 temp,传入对象 coor 的 m_iX 要和

当前对象的
m_iX 相加,赋值给临时对象 temp 的 m_iX,而对于

m_iY 同理 … 最后将 temp 作为返回值返回出去

在使用时:

定义 3 个 Coordinate 的对象 coor1、coor2、coor3,用 coor3 来

接收
coor1 与 coor2 相加的和,这里的加号 + 就已经用到了运算符

重载,相当于
coor1.operator+(coor2)

注意:在加号 + 的重载函数 operator+() 的传入参数 coor2 的前面,

其实有一个隐形参数
this,而 this 就相当于传入的第一个参数 coor1

2)再来看友元函数重载,如下:

友元函数重载相对于成员函数重载来说,更能说明问题:

通过
friend 声明将全局函数 operator+() 声明为友元函数,它的两个

参数分别为:const Coordinate &c1 和 const Coordinate &c2

其中,const 可写可不写,如果写上,那么在 operator+() 中就不能再

修改
c1 和 c2 的值了,其实在做加法,即 让一个数与另一个数相加时,

我们也不希望在加的过程当中去修改加数本身的值

所以,加
const 其实是一种设计上的规范

在实现时:

也需要定义一个临时对象 temp,传入参数为 c1 和 c2,c1 的 m_iX

与 c2 的 m_iX 相加,赋值给 temp 的 m_iX,对于 m_iY 同理 … 最后


temp 作为返回值返回出去

在使用时:

使用时,其实和成员函数的加号 + 运算符重载是一样的,仍然要定义

3 个
Coordinate 的对象 coor1、coor2、coor3,将 coor1 与 coor2

相加的和赋值给 coor3,其实就相当于调用 operator+(coor1,coor2)

(2)输出符号 << 的重载

将输出符号 << 的重载声明为友元函数 operator<<(),它的返回值

必须是
ostream&,它的第一个参数也必须是一个
ostream 的引用,

第二个参数是要进行输出的对象
或引用(引用效率更高)

在实现时:

将 ostream 的对象引用 out 替代原来写成 cout 的位置,其他写法不变,

分别输出
m_iX 和 m_iY 的值,并一定要将 out 作为返回值返回出去

在使用时:

定义一个 Coordinate 的对象 coor,通过 cout 就可以直接输出 coor 的

m_iX 和 m_iY,如果不进行运算符重载,这样写肯定是错误的,进行运算

符重载之后,这样写就相当于
operator<<(cout,coor)

通过这个例子,从侧面也能看出: cout 其实就是一个对象,并且是一个

ostream 类型的对象

那么,输出运算符可以采用成员函数进行重载吗?

从成员函数重载的特点说起:

如果使用成员函数重载,如:上面的加号
+ 运算符的重载,传入的

只有一个参数,这个参数其实是第二个加数,第一个加数默认就是

隐形的
this 指针,即 当前对象

可是,对于输出运算符来说,第一个参数必须是
ostream 的引用,

这就意味着第一个参数不能是隐形的
this 指针,二者是相冲突的

所以,当重载输出运算符 << 时,绝对不可以通过成员函数进行

重载,必须使用友元函数进行重载

(3)索引符号 [] 的重载

索引运算符 [] 更多的运用在数组上,这里先运用到
Coordinate 类中:

在声明时,将之作为一个成员函数放在类中,定义方法:operator[]()

因为它是索引,所以要传入一个
int 型的变量作为索引,而返回值

要么是
m_iX,要么是 m_iY

在实现时:

判断传入的
index 参数:

如果等于 0,就将 m_iX 作为返回值返回出去,如果等于 1,就将 m_iY

作为返回值返回出去,如果是其他值,暂不处理,实际上应该抛出异常

在使用时:

定义一个
Coordinate 的对象 coor,如果通过 cout 输出 coor 的

0 号元素,即 输出横坐标 m_iX,如果输出 coor 的 1 号元素,即

输出纵坐标 m_iY

当调用 coor 接索引时,其实就相当于调用 coor.operator[]()

那么,索引运算符可以采用友元函数进行重载吗?

答案是否定的,不能采用友元函数进行重载。原因是友元函数重载,

它的第一个参数可以是成员函数重载中的隐形
this 指针,也可以是

其它值

但作为索引运算符来说,
它的第一个参数必须是
this 指针,因为

只有第一个参数是
this 指针,才能够传入索引,并使得这个索引

所表达的是当前对象中的数据成员

所以,索引运算符必须采用成员函数进行重载,无法使用友元函数

进行重载

程序:

Coordinate.h:


#ifndef COORDINATE_H

#define COORDINATE_H

#include <iostream>

using namespace std;

class Coordinate

{

//+号运算符的友元函数重载
与注释掉的成员函数重载做对比

//可以给参数加const 毕竟在做加法运算时不希望加数出现变化

friend Coordinate operator+(Coordinate &c1, Coordinate &c2);

//输出运算符重载只能是友元函数重载

//因为其传入的第一个参数必须是ostream的一个引用
(引用的名字任意
只要合法)

//

//而根据成员函数重载的特点
传入的第一个参数

//是this指针(隐形)
也就是当前对象
二者相冲突
所以只能是友元函数重载

//

//第二个参数是要输出的一个对象或者引用(引用效率更高)

//可以加它一个const 即const Coordinate coor;

//返回值必须是ostream 加一个引用 &

friend ostream &operator<<(ostream &output, Coordinate &coor);

public:

Coordinate(int x, int y);

//+号运算符的成员函数重载
返回值是一个Coordinate的对象

//第一个参数是当前的对象
也就是隐形的this指针(第一个操作数)

//第二个就是这里明面上的引用(第二个操作数)

//

//即默认第一个加数是当前对象
第二个加数是传入的参数

//可以给参数加const 毕竟在做加法运算时不希望加数出现变化

//

//Coordinate operator+(Coordinate &c);

//索引运算符只能是成员函数重载
因为友元函数重载的第一个参数

//可以是成员函数重载中的那个this指针
也可以是其他的值

//

//但作为索引运算符来说
它的第一个参数必须是this指针

//因为只有第一个参数是this指针
才能够传入索引

//才能够使得这个索引表达的是当前这个对象中的成员

//

//在这个例子中
第一个参数一定是this指针
它表达是Coordinate的一个对象

//接下来传入的0或者是1:

//所表达的就是这个传入的this指针所指向的对象当中的0号元素或者1号元素

//所谓0号元素就是当前对象的X值
所谓1号对象就是当前对象的Y值

//所以只能采用成员函数进行重载

int
operator[](int index);

int getX();

int getY();

private:

int m_iX;

int m_iY;

};

#endif

Coordinate.cpp:


#include
"Coordinate.h"

#include <ostream>

Coordinate::Coordinate(int x, int y)

{

m_iX = x;

m_iY = y;

}

int Coordinate::getX()

{

return m_iX;

}

int Coordinate::getY()

{

return m_iY;

}

//Coordinate Coordinate::operator+(Coordinate &c)

//{

// //先定义一个临时的对象temp 并初始化

// Coordinate temp(0, 0);

// //当前对象(即this指针)和传入的对象横坐标相加

// temp.m_iX = this->m_iX + c.m_iX;

// temp.m_iY = this->m_iY + c.m_iY;

// return temp;

//}

Coordinate operator+(Coordinate &c1, Coordinate &c2)

{

Coordinate temp(0, 0);

temp.m_iX = c1.m_iX + c2.m_iX;

temp.m_iY = c1.m_iY + c2.m_iY;

return temp;

}

//因为使用了ostream类
在头文件要包含 #include<ostream>

ostream &operator<<(ostream &output, Coordinate &coor)

{

//注意这里就不需要getX()和getY()了

//因为这里是友元
可以直接访问其数据成员

output << coor.m_iX << "," << coor.m_iY;

//返回的是ostream类型的对象

return output;

}

//注意返回类型是int型

int Coordinate::operator[](int index)

{

if (0 == index)

{

return m_iX;

}

if (1 == index)

{

return m_iY;

}

//如果既不是0 也不是1 就应该抛出异常

}

main.cpp:


#include
"stdlib.h"

#include
"Coordinate.h"

int main(void)

{

Coordinate coor1(1, 3);

Coordinate coor2(2, 4);

Coordinate coor3(0, 0);

//coor3 = coor1 + coor2;//coor3 = coor1.operator+(coor2);

coor3 = coor1 + coor2;//coor3 = operator+(coor1,coor2);

cout << coor3.getX() << "," << coor3.getY() << endl;

//operator<<(cout,coor3);

//由此可知 cout实际上是一个对象
是一个ostream类型的对象

cout << coor3 << endl;

cout << coor3[0] << endl;//coor.operator[](0);

cout << coor3[1] << endl;//coor.operator[](1);

system("pause");

return
0;

}

【made by siwuxie095】

时间: 2024-07-30 12:12:47

二元运算符重载的相关文章

C++之运算符重载(二元)

一.加号+ 1.成员函数重载 2.友元函数重载 二.输出符号<< 三.索引符号 [ ] 四.补充说明 1.<二元运算符重载>课程评论: (一)为什么<<运算符的重载必须定义为友元 如果在类中定义非友元成员函数,默认第一个参数默认会传入this*指针,这时就无法实现cout在前<<对象在后的格式 因为二元运算符中的调用格式是 参数一 运算符 参数二 这也就是为什么 加号运算符可以使用非友元成员函数,因为参数一是一个this*指针,参数二是其它对象 假设定义为非

运算符重载(三)

我们知道运算符重载函数可以选择两种形式(1)成员函数形式   (2) 全局友元函数形式.那么我们应该怎么样选择呢? 首先按照语法规定有的运算符只能由成员函数重载的运算符,例如operator[],operator=.而有些运算符既可以用成员函数重载,也可以冲全局友元函数重载,例如:++ ,——,+,—,+=,—=等,像这种既可以用成员函数重载也可以用全局友元函数重载的运算符,我们建议用成员函数重载,因为这样做强调了运算符和类的联合,尤其是二元运算符重载时,当左侧操作数是当前的对象时,运算符会工作

《C++编程思想》 第十一章 运算符重载 (习题+解答)

一.相关代码 1. /*运算符重载语法*/ /*OPOVER.cpp*/ /*这两个重载的运算符被定义为内联成员函数.对于二元运算符,单个参数是出现在运算符 右侧的那个.当一元运算符被定义为成员函数时,没有参数.成员函数被运算符左侧的对象调 用. 对于非条件运算符(条件运算符通常返回一个布尔值),如果两个参数是相同的类型,希 望返回和运算相同类型的对象或引用.如果它们不是相同类型,它作什么样的解释就取决于程 序设计者.用这种方法可以组合复杂的表达式: K += I + J ; 运算符+号产生一个

新标准C++程序设计读书笔记_运算符重载

形式 返回值类型 operator 运算符(形参表) { …… } 运算符重载 (1)运算符重载的实质是函数重载(2)可以重载为普通函数,也可以重载为成员函数 1 class Complex 2 { 3 public: 4 double real,imag; 5 Complex( double r = 0.0, double i= 0.0 ):real(r),imag(i) { } 6 Complex operator-(const Complex & c); 7 }; 8 9 Complex

运算符重载 学习总结

一元运算符重载 参考https://www.imooc.com/video/9588 - 号 友元函数重载 略 成员函数重载 class A{ public: A& operator-(); private: int m_a; int m_b; } A& A::operator-();{ m_a = -m_a; m_b = -m_a; return *this; } ++号(前置与后置) 略 二元运算符重载 参考https://www.imooc.com/video/9591 +号 成员函

C++运算符重载——重载二元运算符

1.重载二元操作符的方法 二元运算符又称为双目运算符,即需要2个操作数的运算符,例如 + - * / 等. 运算符重载可以分为3种方式:类的非静态成员函数.类的友元函数.普通函数. 例如有 2 个操作数 a 和 b,二元运算符 ? (表示一个二元运算符),a ? b 的操作会被解释为下面2种形式之一 //a ? b a.operator?(b); //类的非静态成员函数 operator?(a, b); //友元函数 和 普通函数 第一种形式是运算符被重载为类的非静态成员函数, 这种方式要求运算

运算符重载

关键字:operator 相见:<高质量程序设计指南> P255 如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符. 如果运算符被重载为类的成员函数,那么一元运算符没有参数(但是++和--运算符的后置版本除外),二元运算符只有右侧参数,因为对象自己成了左侧参数. 运算符重载的特殊性 如果重载为成员函数,则this对象发起对它的调用 如果重载为全局函数,则第一个参数发起对它的调用 禁止用户发明该语言运算符集合中不存在的运算符 除了函数调用运算符

关于c++的运算符重载那些事

搞c++有一段时间了,今天突然要重载一个运算符,发现自己有点忘了,遂查查资料做一下c++运算符重载的小总结. 一.何为运算符重载 运算符的重载是c++语言特有的,java什么的是没有运算符重载的,所以运算符重载在笔试面试中有可能成为c++的高频考点.运算符重载就是重新定义运算符的意义,如常用的+,-,×,÷都是可以重载的.运算符重载使用的是关键字operator,表现形式是:                                                            

C#中的运算符重载

C# 允许用户自定义类型通过使用 operator 关键字定义静态成员函数来重载运算符. 注意: 必须用public修饰,必须是类的静态的方法. 重载相等运算符(==)时,还必须重载不相等运算(!=). < 和 > 运算符以及 <= 和 >= 运算符也必须成对重载. 可以重载的运算符: 可以重载的一元运算符:+.-.!.~.++.--.true 和 false 可以重载的二进制运算符:+, -, *, /, %, &, |, ^, <<, >> 可以