------------------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】