运算符重载是具有返回值,参数列表的具有特殊函数名的函数
函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 + operator + 操作符 + 参数列表
注意:形参看起来要比操作数数目少1个成员函数
运算符重载分为:全局的operator和局部的operator
我们常用局部的:
class Date{
public:
Date(int year = 1900,int month = 1,int day = 1){
_year = year;
_month = month;
_day = day;
}
bool operator==(const Date& d){
return _year == d._year &&
_month = d._month &&
_day = d._day;
}
}
int main(){
Date d1;
Date d2(2019,5,17);
cout << (d1 == d2) << endl;
}
我们调用运算符重载的时候就跟普通的形式类似,但是定义确实针对性的不同。
我们可以看到上面定义中只有一个参数,而我们调用的时候是两个参数的,一个d1,一个d2;实际上定义的时候形参只写了右边的即d2的,而左边d1的我们使用*this指针隐含的标识了,所以会出现形参少一个的情况。
赋值运算符是上面运算符重载的一个,即operator后面的运算符号是“=”
赋值运算符的特点主要由五点:
1.参数类型
2.返回值
3.检测是否自己给自己赋值
4.需要返回*this指针
5.一个类如果没有显示的定义赋值运算符重载,编译器就会自己生成,完成对象按照字节序的值拷贝,即浅拷贝或值拷贝
这里说的返回值指的是:我们不再仅是内置类型,而且包含自定义类型,即返回的不仅int、double等类型还包含自定义的Date类型等。
参数类型与返回值类型相似
赋值运算符是需要检测是否自己给自己赋值的,这里主要检测的就是自己不能给自己赋值,这时为什么呢?因为我们形参说了不是传值拷贝就是引用形式,传值拷贝会调用拷贝构造函数,会产生临时空间,效率降低;这时候如果进行自己赋值给自己,那么这样的值拷贝就会出现一个严重的问题,即被拷贝的与拷贝结果在内存中共同处于同一块空间,指向同一个内存地址;这样的话,如果需要析构函数进行清理工作的时候,调用一个变量的析构函数会析构两个变量,造成错误;这时候有人说了我们使用引用不就行了,这同样也是错误的,因为引用出来的被拷贝的对象与拷贝结果在内存中也是指向同一个地址的,析构的时候仍然会出错,这就是为什么不让进行自己给自己赋值的原因。
注意:
Date d1;Date d2;d1 = d2;
与
Date d1; Date d2 = d1;
这两者间的区别,上面的是赋值运算符,下面的是拷贝构造函数。
产生的原因就是书写的相似性,最大的区别就是一个初始化的时候进行了赋值,那么这个就是拷贝构造;一个是都初始化好了,使用的时候进行赋值,那么就是赋值运算符的调用。