3. 运算符重载
在日期类中定义一个对象:
Date d1(2023,7,31);
假设现在想要计算100天
后是几月几号的话,直接使用+
无法实现这个功能!
Date d2 = d1+100; //普通的加号不能实现此功能
C++中,普通的加号只适用于内置类型
而自定义类型的加号种类太多
系统没有自行实现,需要用户自己写!
要自己实现的运算符需要运算符重载!
C++为了增强代码的可读性
引入了运算符重载
运算符重载是具有特殊函数名的函数
也具有其返回值类型,函数名字
以及参数列表
其返回值类型和参数列表与普通函数类似
使用关键字: operator
函数原型:
返回值类型 operator操作符(参数列表)
举例说明日期类+号的重载:
Date operator+(Date d1, int x); • 1
3.1 对运算符重载的思考
运算符重载是针对自定义类型的
所以函数参数中必须有一个类类型参数
但是,如果运算符重载写在类外
它就不能访问类中的私有成员!
所以常常将运算符重载写在类中!
比如:
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } bool operator==(const Date& d2) { return _year == d2._year; && _month == d2._month && _day == d2._day; } private: int _year; int _month; int _day; };
写在类中时,类类型参数可以省略!
因为类中函数默认有this指针
指针this就代表了此类对象了!
3.2 特殊的赋值运算符
赋值运算符十分特殊
若我们不显示写,编译器会自动生成一个
所以赋值运算符只能写在类中
如果显示写在了类外的话
编译器会自动生成一个赋值函数
这就和你自己写的冲突了!
Date& operator=(const Date& d) { if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; }
注:this是类对象的地址
*this就是类对象本身
赋值运算符返回类对象的原因是:
多次连续赋值
Date d1(2023,7,31); Date d2; Date d3; d2 = d3 = d1;//连续赋值
拓展:
编译器自动生成的默认赋值运算符重载,以值的方式逐字节拷贝。
注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值
总结:
如果类中未涉及到资源管理
赋值运算符是否实现都可以
一旦涉及到资源管理则必须要实现
3.3 前置++和后置++
对于++的运算符重载比较有争议
因为前置和后置是两种不同的函数!
C++为了区分前置和后置++
在后置++的函数中多加一个int
类型的参数来区别前置++
比如:
前置++:
Date& operator++();
后置++:
Date& operator++(int);
注意,虽然后置++多了一个参数
但是这个参数完全没用!
只用于区别前置++
++运算符的使用:
Date d1(2023,7,31); //前置++ ++d1; //后置++ d1++;
虽然后置++多了一个参数
但是不需要我们显示传参
编译器会自动帮助我们传参!
3.4 运算符重载再理解
先看以下日期类代码:
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } bool operator==(const Date& d2) { return _year == d2._year; && _month == d2._month && _day == d2._day; } Date& operator=(const Date& d) { if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; } private: int _year; int _month; int _day; };
现在定义类对象进行操作:
Date d1(2023,7,31); Date d2(2023,7,30); if(d1==d2) { cout<<"d1和d2相同"; } Date d3; d3 = d1;
上面的代码中调用了两个运算符重载函数
operator=和operator==
实际上调用 == 时是这样的:
调用 = 时是这样的:
4. 总结以及拓展
写运算符重载函数时,尽量使用引用传参
const Date&
若传值传参,会调用拷贝构造,效率很低
有几个操作符不能被运算符重载:
- .*
- ::
- sizeof
- ?:
- .
C++中拷贝构造和赋值运算符容易混淆
Date d1(2023,7,31); Date d2 = d1; Date d3; d3 = d1;
d2=d1是调用了拷贝构造函数
d3=d1是调用了赋值运算符重载
关于更多拷贝构造和赋值的关系
可以参考这篇文章:
🔎 下期预告:类和对象(下) 🔍