自增|自减|运算符重载

参考

  1. https://blog.shipengx.com/archives/5ac252d6.html
  2. 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++

尽管传入的值通常会被运算符函数忽略,但却必不可少,因为编译器只有通过它才能知道应该使用后置版本。

posted @ 2022-12-08 16:34  ethon-wang  阅读(15)  评论(0编辑  收藏  举报