目录
💕1.运算符重载何时使用
💕2.运算符重载的定义
💕3.分析两段代码
目录3:总结->:
💕4.运算符重载前置与后置++(或者类似情况)的写法
(最新更新时间——2025.1.15)
风雪虽寒
也就这般
💕1.运算符重载何时使用
如果不做特殊处理,C++ 的 +、-、*、/ 等运算符只能用于对基本类型的常量或变量进行运算,不能用于对象之间的运算。
什么意思?请看图片->:
当我们创建两个类的对象时,我们想让这两个对象进行操作符运算(如:+,-,*,/,==等)都是不可以直接运算的,这时候就要运用到运算符重载
💕2.运算符重载的定义
1.运算符重载是具有特殊名字的函数,他的名字是由operator和后面要定义的运算符共同构成。和其他函数⼀样,它也具有其返回类型和参数列表以及函数体
2.重载操作符必须有一个类类型参数
3.用于operator的运算符,其含义不能变,例如:operator函数里面实现的是+的功能,你不能命名成operator-(但其实你更改也没有关系,编译器识别不出来)
4.作为类成员函数重载时,其形参看起来比操作数少1,因为成员函数的第一个参数为隐藏的 this
5.以上5个运算符不能用于重载,这个经常在笔试题中出现
什么意思?请看代码->:
#include<iostream> #include<stdlib.h> using namespace std; class Date { public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;} public:int _year;int _month;int _day; }; //可以换返回类型与形参 bool operator==(Date& s1, Date& s2) {if (s1._year == s2._year){if (s1._month == s2._month){if (s1._day == s2._day){return true;}}}else{return false;} } int main() {Date s1(2025, 1, 15);Date s2(2024, 1, 1);operator==(s1, s2);//等价operator==(s1, s2);s1 == s2; }
如代码所示:我们利用关键字operator加上操作符,就可以让两个类类型的对象之间使用操作符,我们也可以自己更改操作符,operator关键字后面的操作符是给你自己识别的,你可以随意更换
在我们使用operator关键字后,我们使用s1 == s2,实际上调用的就是 operator==(s1, s2);
注意!!!!!我在代码中类的成员变量都是public,这是因为如果是private,那么在类外的operator中就无法访问到year,month,day
接下来我们讲一下第四点
先看代码->:
#include<iostream> #include<stdlib.h> using namespace std; class Date { public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}bool operator==(Date& s1,Date& s2){if (_year == s2._year){if (_month == s2._month){if (_day == s2._day){return true;}}}else{return false;}} private:int _year;int _month;int _day; };int main() {Date s1(2025, 1, 15);Date s2(2024, 1, 1);operator==(s1,s2);//s1==s2等价于operator==(s1,s2)s1 == s2; }
如果我们这么写,编译器是会报错的,这是因为运算符重载作为类成员函数重载时,运算符重载的形参个数应该与实际需要操作的对象个数相同,而当我们放在类中时,我们讲到过类中的成员函数是有一个隐藏的this指针的,所以operator函数实际上有三个形参,这就导致多出一个形参,这是不可以的,对此,我们的操作应该是,"巧妙地应用this指针"
请看接下来的代码->:
#include<iostream> #include<stdlib.h> using namespace std; class Date { public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}bool operator==(Date& s2){return _year == s2._year&& _month == s2._month&& _day == s2._day;} public:int _year;int _month;int _day; };int main() {Date s1(2025, 1, 15);Date s2(2025, 1, 15);s1.operator==(s2);//s1==s2等价于s1.operator==(s2)if (s1 == s2){cout << "true" << endl;}else{cout << "false" << endl;} }
我们在类中的运算符重载,可以减去一个形参,在main函数中使用s1.operator,这样就会把s1的地址传给this指针,这样就不会导致形参个数为3超出实际操作形参为2的因果
💕3.分析两段代码
Date func() {Date d(2025, 1, 15);return d; } int main() { Date& ref = func(); }
第一段代码如上,分析一下不好的地方以及错在哪里?
首先->:指出最简单的错误,return返回的值是一个临时变量,临时变量具有常性,也就是说明临时变量不可以修改,所以在main函数中用ref接受时,应该用const修饰
接下来不好点写在更改后的代码中->:
Date func() {//调用d的构造函数Date d(2025, 1, 15);//返回d时会执行Date tep = d,再将tep返回回去,这里的Date tep = d,会调用拷贝构造函数,影响内存与运行时间return d; } int main() { //用const修饰,不然会权限的放大const Date& ref = func();//注意://如果写成以下->:const Date ref = func();//这么写又会调用一次拷贝构造函数了,所以应该用引用 }
再看一段代码吧
Date& func() {Date d(2025, 1, 15);return d; }int main() { const Date& ref = func(); }
这段代码有没有问题呢?
其实也是有的,虽然看似没问题,但其实这里有一个野引用
详解写在以下代码中了
Date& func() { Date d(2025, 1, 15);//(最后看)如果写成static Date d(2025,1,15);可以避免//返回时执行的是Date& tep = d,这里属于引用,没有调用拷贝构造函数,也就是不会开辟新的空间//再将tep返回去return d; }int main() { //这里的ref接受了tep,也就说明ref就是d的别名//但需要注意的是,d是一个类的对象,d的生命周期结束时会自动调用类的析构函数,也就会释放d的内存空间,这就导致ref指向的是一块未知的空间,就会形成野引用//这就导致当ref指向的空间被别的栈区使用时,就会更改ref的值,这是非常危险的const Date& ref = func(); }
目录3:总结->:
出了作用域,返回对象还在没有析构,那就可以用引用返回,减少拷贝
a、返回对象生命周期到了,会析构,传值返回
b、返回对象生命周期没到,不会析构,传引用返回
💕4.运算符重载前置与后置++(或者类似情况)的写法
在使用运算符重载时,为了区分是前置++还是后置++,祖师爷规定:
为了区分,构成重载,给后置++,强行增加了一个int形参
这里不需要写形参名,因为接收值是多少不重要,也不需要用
这个参数仅仅是为了跟前置++构成重载区分
请看代码->:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Date { public:Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day; };//前置++ Date& operator++(Date& s1, int) {cout << "前置++" << endl;return s1; }//后置++ Date& operator++(Date& s1) {cout << "后置++" << endl;return s1; } int main() {Date d1(2025, 1, 15);operator++(d1);operator++(d1, 5);cout << d1._day; }
各位可以自己运行一下,我将运行截图放在下面: