自增|自减|运算符重载
参考
- https://blog.shipengx.com/archives/5ac252d6.html
- https://blog.csdn.net/qq_29762941/article/details/80973027
#include<iostream>
using namespace std;
class point{
public:
point(int a,int b):x(a),y(b){}
point& operator++(){//前置运算符,需要引用返回,不需要参数。返回自增后的值,且返回的是一个左值
x++;
y++;
return *this;
}
point operator++(int){//后置++,不需要引用返回,需要参数区分。返回自增前的值,且返回的是一个右值
point temp(x,y);
x++;
y++;
//cout<<"x1 = "<<temp.x<<",y1 = "<<temp.y<<endl;
return temp;
}
void show(){
cout<<"x = "<<x<<",y = "<<y<<endl;
}
private:
int x;
int y;
};
int main(){
point p(2,3);
p.show();
p++;
p.show();
++p;
p.show();
return 0;
}
14.6 递增和递减运算符
C++ 语言并不要求递增和递减运算符必须是类的成员,但是因为它们改变的正好是所操作对象的状态,所以建议将其设定为成员函数。
Best Practices:定义递增和递减运算符的类应该同时定义前置版本和后置版本。这些运算符通常应该被定义成类的成员。
Best Practices:为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
要想同时定义前置和后置运算符,必须首先解决一个问题,即普通的重载形式无法区分这两种情况。前置和后置版本使用的是同一个符号,意味着其重载版本所用的名字将是相同的,并且运算对象的数量和类型也相同。
为了解决这个问题,后置版本接受一个额外的(不被使用)int 类型的形参。当我们使用后置运算符时,编译器为这个形参提供一个值为 0 的实参。尽管从语法上来说后置函数可以使用这个额外的形参,但是在实际过程中通常不会这么做。这个形参的唯一作用就是区分前置版本和后置版本的函数,而不是真的要在实现后置版本时参与运算。
Best Practices:为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用。
对于后置版本来说,在递增对象之前需要首先记录对象的状态:
// 后置版本:递增/递减对象的值但是返回原值
StrBlobPtr StrBlobPtr::operator++(int)
{
// 此处无须检查有效性,调用前置递增运算时才需要检查
StrBlobPtr ret = *this; // 记录当前的值
++*this; // 向前移动一个元素,前置 ++ 需要检查递增的有效性
return ret; // 返回之前记录的状态
}
StrBlobPtr StrBlobPtr::operator--(int)
{
// 此处无须检查有效性,调用前置递减运算时才需要检查
StrBlobPtr ret = *this; // 记录当前的值
--*this; // 向后移动一个元素,前置 -- 需要检查递减的有效性
return ret; // 返回之前记录的状态
}
Note: 因为我们不会用到 int 形参,所以无须为其命名。
如果我们想通过函数调用的方式调用后置版本,则必须为它的整型参数传递一个值:
StrBlobPtr p(a1); // p 指向 a1 中的 vector
p.operator++(0); // 调用后置版本的 operator++
p.operator++(); // 调用前置版本的 operator++
尽管传入的值通常会被运算符函数忽略,但却必不可少,因为编译器只有通过它才能知道应该使用后置版本。