------------------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值
//所以只能采用成员函数进行重载
intoperator[](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");
return0;
}
【made by siwuxie095】