看完了基础的语法,我们来讨论几个实例。
1. ++运算符重载
①. 前置自增运算符的重载
成员函数方式:
函数原型& operator++() ;
友元函数方式:
friend 函数原型& operator++(类名&) ;
②. 后置自增运算符的重载
成员函数方式:
函数原型& operator++(int) ;
友元函数方式:
friend 函数原型 operator++ (类名& , int) ;
前置的写法如下:
#include <iostream>
using namespace std ;
class Integer{
int i_ ;
public :
Integer(int i) : i_(i) { }
~Integer() { }
Integer& operator++() {
++ i_ ;
return *this ;
}
friend Integer& operator++(Integer& i) ;
void Display() {
cout << i_ << endl ;
}
};
Integer& operator++(Integer& n) {
++ n.i_ ;
return n ;
}
int main(void) {
Integer n1(100) ;
n1.Display() ;
Integer n2 = ++ n1 ;
n2.Display() ;
return 0 ;
}
在后置重载函数的写法中,参数列表多了一个参数int , 实际上这个参数是一个哑元变量,在实际的运行中不起作用,仅是用来区分前置自增与后置自增。
但请大家思考一下,前置自增与后置自增的区别难道仅仅是多了一个哑元变量吗?
答案是否定的,如果真的仅此而已的话,那么前置与后置就没有任何区别了。
我们先来看看后置自增的定义:在表达式中,先按照原值参与计算,表达式结束后再进行自增。
比如如下表达式:
int i = 3 ;
int j = i ++ ;
i 会先将3赋值给 j , 等表达式中所有的运算结束后,再自增。
结果:i = 4 ; j = 3 ;
因此,为了能体现后置自增的特性,我们应该这样实现:
#include <iostream>
using namespace std ;
class Integer{
int i_ ;
public :
Integer(int i) : i_(i) { }
~Integer() { }
Integer& operator++(int x) {
Integer before(i_) ;
++ i_ ;
return before ;
}
friend Integer operator++(Integer& self , int x) ;
void Display() {
cout << i_ << endl ;
}
};
Integer operator++(Integer& n , int x) {
Integer before(n) ;
++ n.i_ ;
return before ;
}
int main(void) {
Integer n1(100) ;
n1.Display() ;
Integer n2 = n1++ ;
n1.Display() ;
n2.Display() ;
return 0 ;
}
这样的做法满足后置自增的语法,先将原值保存起来,再自增,最后返回原值自增前的副本。
此处,我们应该返回一个临时对象而不是引用。
因为我们已经修改了当前的对象。