05-3 运算符重载-递增递减
递增递减重载的作用:让结构体或者类可以直接完成递增递减,无需将数据单独从结构体或者类拿出来。
完成左移运算符重载有两种方法:
- 在成员函数里面实现重载。
- 在全局函数里面实现重载。
使用重载的时候,需要使用关键字operator
。递增递减重载的函数声明是(准确说是以递增++
为例):前置:类名称& operator++();
,后置:类名称 operator++(int);
-
复习一下递增递减(以递增为例)
在 c++中,有递增这种运算。递增的作用让变量在自身身上加一。常见的用递增的,是在写
for
循环的时候,比如:for (int i = 0; i < 10; i++) { cout << "Hello!" << endl; }
在上面的例子中,运行完成
for
下的代码块的内容的时候,会给i
加一,简单的可以认为,i++
等价于i = i + 1
或者是i += 1
。而在递增中,又分为前置递增和后置递增两种。
-
前置递增
前置递增是在运行这一行代码或者表达式之前就进行递增运算。
int a = 10; cout << a << endl; cout << ++a << endl; cout << a << endl;
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
10 11 11
在上面的例子中,
cout << ++a << endl;
相当于运行了两行代码:(注意运行的先后顺序。)a = a + 1; cout << a << endl;
-
后置递增
后置递增是在运行这一行代码或者表达式之后才进行递增运算。
int a = 10; cout << a << endl; cout << a++ << endl; cout << a << endl;
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
10 10 11
在上面的例子中,
cout << a++ << endl;
相当于运行了两行代码:(注意运行的先后顺序。)cout << a << endl; a = a + 1;
而递减运算,和递增基本相同,也分为前置和后置。但是,与递增运算有区别的是,递减运算是在原数的基础上减去1。
-
如何进行递增递减重载,以递增为例。
-
前置递增的重载
请注意:前置递增重载的函数声明:
class test& operator++()
class test& operator++() { m_A++; m_B++; return *this; }
-
为什么返回的是引用:
这是为了实现重复的递增。比如:
a = 10; cout << ++(++a) << endl;
运行结果:
12
如果我们重载的时候不是以引用返回,那么如果运行一下这样:
class test t1; cout << ++(++t1) << endl;
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
m_A = 11 m_B = 11
如果使用引用返回,那么则是:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
m_A = 12 m_B = 12
看一眼代码:
#include
using namespace std; class test { friend ostream& operator<<(ostream& cout, class test& p); private: int m_A; int m_B; public: test() { m_A = 10; m_B = 10; } test& operator++() { m_A++; m_B++; return *this; } }; ostream& operator<<(ostream& cout, class test& p) { cout << "m_A = " << p.m_A << " m_B = " << p.m_B; return cout; } int main() { class test t1; ++t1; cout << t1 << endl; return 0; } 当然,我们也可以在全局函数完成重载:
class test& operator++(class test& p) { p.m_A++; p.m_B++; return p; }
-
-
后置递增的重载
请注意:后置递增重载的函数声明:
class test& operator++(int)
在后置递增中,函数形参列表中有一个
int
,这是int
做占位参数,即:函数的占位参数。如果有了这个int
,编译器就会知道这是后置的递增而非前置递增。class test operator++(int) { class test temp = *this; m_A++; m_B++; return temp; }
-
为什么这里返回的不是
this
指针。因为函数的数据存放在堆区。堆区数据在运行完成后会自动释放,所以不能返回堆区的指针。
-
为什么返回引用。
首先是上面说的,存放在堆区数据会释放。
其次是,如果连续两个后置递增在
int
等的类型下也是会报错的。
完整看一眼代码:
#include
using namespace std; class test { friend ostream& operator<<(ostream& cout, class test& p); private: int m_A; int m_B; public: test() { m_A = 10; m_B = 10; } class test operator++(int) { class test temp = *this; m_A++; m_B++; return temp; } }; ostream& operator<<(ostream& cout, class test& p) { cout << "m_A = " << p.m_A << " m_B = " << p.m_B; return cout; } int main() { class test t1; t1++; cout << t1 << endl; return 0; } 但是,后置递增不能出现在全局函数中重载。但是如果是在想在全局函数中重载,可以使用设置作用域的方式。
即:
在类中声明函数,在类外定义函数。
比如说:
class test { private: int m_A; int m_B; public: test() { m_A = 10; m_B = 10; } class test operator++(int); }; ostream& operator<<(ostream& cout, class test& p) { cout << "m_A = " << p.m_A << " m_B = " << p.m_B; return cout; } class test test::operator++(int) { class test temp = *this; m_A++; m_B++; return temp; }
-
-
递减的做法:
-
前置递减
class test& operator--() { m_A--; m_B--; return *this; }
-
后置递减
class test operator--(int) { class test temp = *this; m_A--; m_B--; return temp; }
-
- 总结:
- 前置递增(递减)需要使用引用的方式返回,返回值是
*this
,用于实现连续的递增(递减运算)。 - 后置递增(递减)返回的是一个临时的变量,不可以使用引用的方式返回。
- 后置递增(递减)的形参列表需要添加
int
做占位。 - 后置递增(递减)无法实现连续的递增(递减)。
- 前置递增(递减)需要使用引用的方式返回,返回值是
:-)