大家好,我是苏貝,本篇博客带大家了解C++的运算符重载,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
目录
- (A) 引入
- (B) 运算符重载
(A) 引入
写一个Date日期类,问:如果我们想比较两个日期d1、d2是否相等,可以直接d1==d2吗?
不能,因为C++的运算符只能对内置类型使用,对自定义类型会报错。所以我们如果想比较两个日期的大小,就要自己写函数
下面的函数写在全局域里,形参用引用而非对象的传值传参,因为如果是传值传参,那就需要调用对象的拷贝构造,如果用引用就不需要。
函数体内对象的引用x和y能直接访问成员变量的原因是Date类中,成员变量是public
因为函数内只需要对相应的成员变量做比较,不需要改变它们的值,因此形参用const修饰,来保证它们不能被修改
写好了比较函数之后,我们就可以比较两个日期的大小了
我们这三个函数的函数名写的还不错,能明白是什么意思,那如果现在有人写了这三个函数,但是函数名分别是func1、func2、func3,我们就不能明白这三个函数分别是什么意思。如果C++能让我们对自定义类型使用==、<、>等运算符,那就再好不过了
(B) 运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
将上面的3个函数分别写成运算符重载
写完了3个运算符重载后,就可以直接用运算符来比较2个日期了,也可以用函数
看下图,为什么会报错?
因为<<的优先级比==、>、<都要高,因此把<<和d1结合到一起,这是不符合我们的要求的。只需要把表达式用括号括起来即可解决这一问题
注意:
是双操作数的操作符时,操作符左右两边的对象要和函数形参的顺序相同,左边对应第一个形参,右边对应第二个形参
为什么编译器能识别对自定义类型的重载后运算符呢?可以理解为,编译器将cout<<(d1== d2)<<endl转换为cout<<oprator==(d1,d2)<<endl
我们以上的3个运算符重载都是定义在全局域,在函数里能用类的成员变量是因为成员变量的访问权限是public,现在将它们的访问权限改为private,3个运算符重载该做什么修改呢?
修改1:
3个运算符重载任然放在全局域,在类里写返回值是成员变量的值的函数
为什么会报错?提示说不能将this指针从const Date转换为Date&,即引用x的类型是const Date,调用成员函数GetYear时,形参this指针的类型是Date。从const Date到Date,权限放大,报错
因此,解决报错的方法:将运算符重载的形参的const去掉
修改2:
将3个运算符重载放到类里
为什么会报错?报错提示说oprator==的参数太多。因为 == 、>、<等都是双操作数的操作符,所以操作数只能有2个,this指针是“成员函数”隐含的第一个指针形参,再加上我们写的x,y一共有3个操作数,所以报错。
解决方法,去掉x,因为x和this都是指向调用成员函数的对象
为什么可以用d1==d2呢?运算符重载不是定义在类里吗?一般在查找函数时,如果不指定类域,是不会到类里面查找的。在这里不一样,当有运算符重载时,如果全局域里有就用全局域的,如果没有就到操作数对应类里面找,还找不到就报错
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@ (新的操作符必须在C/C++中也当作操作符使用)
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义如-
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
- .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
注意:第一个.不是,*可以重载
好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️