运算符重载 使得用户自定义的数据能够更简单的方式工作。
实现运算符重载的两种方法:全局函数 和 成员函数
运算符重载基础: 一元运算符重载(全局函数 类的成员函数)
二元运算符重载
前置++ 前置-- 后置++ 后置--
()
例如:
int a = 0, b = 0;
int c;
c = a + b;//基础数据类型,编译器已经知道了,如何去运算
但是对于复杂的数据类型,比如两个类对象之间,能直接相加吗?
例如
#include <iostream>
using namespace std;
class Complex{//复数类
public:
int a;
int b;
public:
Complex(int a = 0, int b = 0){
this->a = a;
this->b = b;
}
};
int main()
{
// 复数运算规则:a + bi 实部+实部 虚部加虚部
Complex c1(1, 2), c2(3, 4);
Complex c3;
//那么编译器会对下列式子进行复数运算规则的运算吗
c3 = c1 + c2;//显然不会,因为c++编译器对于用户自定义类型,是不知道怎么去运算的
}
这时候,c++编译器应该提供一种机制,让我们程序员有机会对自定义数据类型进行运算符操作,那么这个机制就是传说中的运算符重载机制
运算符重载机制的语法:
我们在不知道的前提下进行探究
步骤一
#include <iostream>
using namespace std;
class Complex{//复数类
public:
int a;
int b;
public:
Complex(int a = 0, int b = 0){
this->a = a;
this->b = b;
}
void print(){
cout << "a: " << a << " " << "b: " << b << endl;
}
};
//定义了全局函数
Complex Add(Complex &a1, Complex &a2){
Complex tmp(a1.a + a2.a, a1.b + a2.b);
return tmp;
}
int main()
{
Complex c1(1, 2), c2(3, 4), c3;
c3 = Add(c1, c2);
c3.print();
return 0;
}
显然我们可以通过这样的方式去实现
步骤二
函数名 升级 我们仅仅是把Add这个函数名 改成了 operator + 这个函数名
#include <iostream>
using namespace std;
class Complex{//复数类
public:
int a;
int b;
public:
Complex(int a = 0, int b = 0){
this->a = a;
this->b = b;
}
void print(){
cout << "a: " << a << " " << "b: " << b << endl;
}
};
/*
//定义了全局函数
Complex Add(Complex &a1, Complex &a2){
Complex tmp(a1.a + a2.a, a1.b + a2.b);
return tmp;
}
*/
//函数名 升级 我们仅仅是把Add这个函数名 改成了 operator + 这个函数名
Complex operator + (Complex &a1, Complex &a2){
Complex tmp(a1.a + a2.a, a1.b + a2.b);
return tmp;
}
int main()
{
Complex c1(1, 2), c2(3, 4), c3;
c3 = operator + (c1, c2);
c3.print();
return 0;
}
这时候,可以进行正确的运行步骤三
那么,我觉得上面的写法不过高端大气上档次,于是在其他代码都不变的情况下,用操作符方式:c3 = c1 + c2 去运算试试
只改变如下代码
int main()
{
Complex c1(1, 2), c2(3, 4), c3;
c3 = c1 + c2;
c3.print();
return 0;
}
可以自己去实践一下,这样当然是完全没有问题地成功了(实现了运算符重载)
总结:运算符重载我们是从函数 “误打误撞” 地得来了,那么,这也让我们探得原来神奇的运算符重载其实本质就是函数。operator 相当于是一个约定。 c++编译器看到比如说c3=c1 + c2 中的 + 号,就会去寻找c1 c2它们的类型中有没有 operator 操作符,如果有,就按重载的操作符来进行运算。