05-1 运算符重载-四则运算
四则运算的运算符重载的作用:让结构体或者类可以直接完成四则运算,无需将数据单独从结构体或者类拿出来。
完成四则运算的运算符重载有两种方法:
- 在成员函数里面实现重载。
- 在全局函数里面实现重载。
使用重载的时候,需要使用关键字operator
。四则运算运算符重载的函数声明是(以加法+
为例):结构体/类名称 operator+(结构体/类名称 变量, 结构体/类名称 变量);
。
为什么我们需要四则运算运算符重载:
-
因为我们在使用类的时候,类如下:
class test { public: int m_A; int m_B; };
这时候实例化出两个对象,
t1
和t2
。如果我希望t1 + t2
是这两个变量的对应的对象分别相加,即t1.m_A + t2.m_A
和t1.m_B + t2.m_B
,这时候我需要写一个函数,比如:class test testAdd(class test* p1, class test* p2) { class test temp; temp.m_A = p1->m_A + p2->m_A; temp.m_B = p1->m_B + p2->m_B; return temp; }
如果直接使用
class test t3 = t1 + t2
这样的命令,是会报错的。但是每次都调用函数都很烦,不如直接+
来的简单直观。所以我们需要四则运算运算符重载。
如何进行四则运算的运算符重载:
-
在成员函数里面实现重载。
-
原先我们是这样写一个类的:
class test { public: int m_A; int m_B; class test testAdd(class test& p) { class test temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } };
在
main
或者运行的时候,需要实现两个test
相加,是这样调用的:class test t3 = t1.testAdd(t2);
或者我们看一眼实际的
main
函数:int main() { class test t1; t1.m_A = 10; t1.m_B = 20; class test t2; t2.m_A = 10; t2.m_B = 20; class test t3 = t1.testAdd(t2); cout << t3.m_A << endl; cout << t3.m_B << endl; return 0; }
-
使用运算符重载:
使用运算符重载的时候,需要使用关键字
operator
。将我们自定义的成员函数的名称修改为operator+
即可:使用重载的成员函数的声明:
class test operator+(class test& p)
class test { public: int m_A; int m_B; class test operator+(class test& p) { class test temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } };
在运行
main
函数或者需要实现两个test
类型相加的时候只需要:class test t3 = t1 + t2;
我们实际看一下:
#include
using namespace std; class test { public: int m_A; int m_B; class test operator+(class test& p) { class test temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } }; int main() { class test t1; t1.m_A = 10; t1.m_B = 20; class test t2; t2.m_A = 10; t2.m_B = 20; class test t3 = t1 + t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } 运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
20 40
-
-
在全局函数里面实现重载。
-
原先我们是写完成两个类的相加的函数的:
class test testAdd(class test& p1, class test& p2) { class test temp; temp.m_A = p1.m_A + p2.m_A; temp.m_B = p1.m_B + p2.m_B; return temp; }
在
main
或者运行的时候,需要实现两个test
相加,是这样调用的:class test t3 = testAdd(t1, t2);
或者我们看一眼实际的
main
函数:int main() { class test t1; t1.m_A = 10; t1.m_B = 20; class test t2; t2.m_A = 10; t2.m_B = 20; class test t3 = testAdd(t1, t2); cout << t3.m_A << endl; cout << t3.m_B << endl; return 0; }
-
使用运算符重载:
使用运算符重载的时候,需要使用关键字
operator
。将我们自定义的全局函数的名称修改为operator+
即可:使用重载的成员函数的声明:
class test operator+(class test& p1, class test& p2)
class test operator+(class test& p1, class test& p2) { class test temp; temp.m_A = p1.m_A + p2.m_A; temp.m_B = p1.m_B + p2.m_B; return temp; }
在运行
main
函数或者需要实现两个test
类型相加的时候只需要:class test t3 = t1 + t2;
我们实际看一下:
#include
using namespace std; class test operator+(class test& p1, class test& p2); class test { public: int m_A; int m_B; }; int main() { class test t1; t1.m_A = 10; t1.m_B = 20; class test t2; t2.m_A = 10; t2.m_B = 20; class test t3 = t1 + t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator+(class test& p1, class test& p2) { class test temp; temp.m_A = p1.m_A + p2.m_A; temp.m_B = p1.m_B + p2.m_B; return temp; } 运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
20 40
-
-
本质:
刚刚我们介绍了如何实现重载,现在我们来讲本质。
- 在成员函数里面实现重载,虽然我们使用的是
class test t3 = t1 + t2;
,但是实际上是class test t3 = t1.operator+(t2);
。 - 在全局函数里面实现重载,虽然我们使用的是
class test t3 = t1 + t2;
,但是实际上是class test t3 = operator+(t1, t2);
。
也就是说,
class test t3 = t1 + t2;
只是一个简化的方法,实际上还是调用成员函数/全局函数。也就是说,运算符重载就是函数,只不过是编译器强制设置名称为operator+
。 - 在成员函数里面实现重载,虽然我们使用的是
-
运算符重载也可以发生函数重载
在上面的例子中,我们使用了两个
class test
的数据类型进行相加,但是如果我们打算让一个class test
的数据类型和一个int
数据类型相加呢?这时候编译器也会报错,这是因为我们之前写的运算符重载都是两个
class test
数据类型的,并没有int
类型的。但是如果我们重新写一下:class test operator+(class test& p1, int num) { class test temp; temp.m_A = p1.m_A + num; temp.m_B = p1.m_B + num; return temp; }
在这里,我们使用函数重载,重新定义
class test
和int
数据类型的相加,之后我们可以试一下:#include
using namespace std; class test operator+(class test& p1, int num); class test { public: int m_A; int m_B; }; int main() { class test t1; t1.m_A = 10; t1.m_B = 20; class test t3 = t1 + 100; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator+(class test& p1, int num) { class test temp; temp.m_A = p1.m_A + num; temp.m_B = p1.m_B + num; return temp; } 运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
110 120
当然,如果突然来一个
class t2 = t1 + 100 + t1;
或者class t2 = t1 + 100 + 200;
这样,也是会报错的。只要按照需求写运算符重载即可。 -
其他运算符的重载。
如笔记标题所言,四则运算。四则运算包括了加减乘除四种运算,其他运算的重载也是大同小异。我们举例说明一下:
-
加(
+
)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)#include
using namespace std; class test operator+(class test& t1, class test& t2); class test { public: int m_A; int m_B; test() { } test(int) { m_A = 10; m_B = 20; } }; int main() { class test t1(1); class test t2(1); class test t3 = t1 + t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator+(class test& t1, class test& t2) { class test ret; ret.m_A = t1.m_A + t2.m_A; ret.m_B = t1.m_B + t2.m_B; return ret; } 20 40
-
减(
-
)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)#include
using namespace std; class test operator-(class test& t1, class test& t2); class test { public: int m_A; int m_B; test() { } test(int) { m_A = 10; m_B = 20; } }; int main() { class test t1(1); class test t2(1); class test t3 = t1 - t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator-(class test& t1, class test& t2) { class test ret; ret.m_A = t1.m_A - t2.m_A; ret.m_B = t1.m_B - t2.m_B; return ret; } 0 0
-
乘(
*
)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)#include
using namespace std; class test operator*(class test& t1, class test& t2); class test { public: int m_A; int m_B; test() { } test(int) { m_A = 10; m_B = 20; } }; int main() { class test t1(1); class test t2(1); class test t3 = t1 * t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator*(class test& t1, class test& t2) { class test ret; ret.m_A = t1.m_A * t2.m_A; ret.m_B = t1.m_B * t2.m_B; return ret; } 100 400
-
除(
/
)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)注意哦!c++中的除法(
/
)是整除哦!#include
using namespace std; class test operator/(class test& t1, class test& t2); class test { public: int m_A; int m_B; test() { } test(int) { m_A = 10; m_B = 20; } }; int main() { class test t1(1); class test t2(1); class test t3 = t1 / t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator/(class test& t1, class test& t2) { class test ret; ret.m_A = t1.m_A / t2.m_A; ret.m_B = t1.m_B / t2.m_B; return ret; } 1 1
-
取模(
%
)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)#include
using namespace std; class test operator%(class test& t1, class test& t2); class test { public: int m_A; int m_B; test() { } test(int) { m_A = 10; m_B = 20; } }; int main() { class test t1(1); class test t2(1); class test t3 = t1 % t2; cout << t3.m_A << "\t" << t3.m_B << endl; return 0; } class test operator%(class test& t1, class test& t2) { class test ret; ret.m_A = t1.m_A % t2.m_A; ret.m_B = t1.m_B % t2.m_B; return ret; } 0 0
-
-
不要滥用运算符重载。
我们上面举例的例子中,无论是加减乘除还是取模,都是在函数中按照重载的符号写相应的代码的。如果在重载加号(
+
)的函数中,实际运行部分写的是减-
,那么就会乱套。所以不要滥用,如果使用运算符重载的时候,一定要好好写,不要捣乱。 -
运算符重载只可以传入引用,不可以传入指针。
引用本质上是一个指针常量,也就是指针的指向的地址不可以修改。但是在运算符重载中,直接传入地址然后指针是无效的。
比如这样:
class test operator+(class test* t1, class test* t2);
如果这样写就会报错:非成员运算符要求类类型或枚举类型的参数
- 总结:
- 内置的数据类型的表达式运算不可以修改。
- 四则运算的运算符重载有两种方法,分别是在成员函数中重载和在全局函数中重载。四则运算运算符重载的函数声明是(以加法
+
为例):结构体/类名称 operator+(结构体/类名称 变量, 结构体/类名称 变量);
。 - 四则运算运算符重载的本质是函数调用。
- 四则运算都可以重载。语法是
operator重载的运算符号
,比如加法就是operator+
。 - 运算符重载可以出现函数重载。
- 不要滥用运算符重载。
- 运算符重载必须使用引用的方法传入。
:-)