本文共 1986 字,大约阅读时间需要 6 分钟。
定义递增和递减运算符的类应该同时定义前置版本和后置版本。这些运算符通常应该被定义成类的成员。
定义前置递增/递减运算符class StrBlobPtr { public: StrBlobPtr& operator++(); StrBlobPtr& operator--();};
为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
递增和递减运算符的工作机理非常相似:它们首先调用check函数检验StrBlobPtr是否有效,如果是,接着检查给定的索引值是否有效。如果check函数没有抛出异常,则运算符返回对象的引用。StrBlobPtr& StrBlobPtr::operator++() { //如果curr已经指向了容器的尾后位置,则无法递增它 check(curr, "increment past end of StrBlobPtr"); ++curr; return *this;}StrBlobPtr& StrBlobPtr::operator--() { //如果curr是0,则继续递减它将产生一个无效下标 --curr; check(curr, "decrement past begin of StrBlobPtr"); return *this;}
区分前置和后置运算符
后置版本接受一个额外的(不被使用)int类型的形参。这个形参唯一的作用是区分前置版本和后置版本的函数,而不是真的要在实现后置版本时参与运算。class StrBlobPtr { public: StrBlobPtr& operator++(int); //后置运算符 StrBlobPtr& operator--(int);};
为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用。
对于后置版本来说,在递增对象之前需要记录对象的状态://后置版本:递增和递减运算符StrBlobPtr StrBlobPtr::operator++(int) { //此处无需检查有效性,调用前置递增运算时才需要检查 StrBlobPtr ret = *this; //记录当前的值 ++* this; //向前移动一个元素,前置++需要检查递增的有效性 return ret; //返回之前记录的状态}StrBlobPtr StrBlobPtr::operator--(int) { //此处无需检查有效性,调用前置递减运算时才需要检查 StrBlobPtr ret = *this; //记录当前的值 --* this; //向后移动一个元素,前置--需要检查递减的有效性 return ret; //返回之前记录的状态}
后置运算符调用各自的前置版本来完成实际的工作。例如后置递增运算符执行
++*this 该表达式调用前置递增运算符,前置递增运算符首先检查递增操作是否安全,根据检查的结果抛出一个异常或者执行递增curr的操作。后置函数返回之前存储的ret的副本。因此,最终的效果是,对象本身向前移动了一个元素,而返回的结果仍然反应对象在未递增之前的原始的值。显式地调用后置运算符
可以显式地调用一个重载地运算符,其效果与在表达式中以运算符号的形式使用它完全一样。如果我们想通过函数调用的方式调用后置版本,则必须为它的整型参数传递一个值:StrBlobPtr p(a1); //P指向a1中的vectorp.operator++(0); //调用后置版本的operator++p.operator++(); //调用前置版本
为你的StrBlobPtr类添加加法和减法运算符,使其可以实现指针的算术运算
class StrBlobPtr { friend StrBlobPtr operator+(int n); friend StrBlobPtr operator-(int n);};StrBlobPtr StrBlobPtr::operator+(int n) { auto ret = *this; ret.curr += n; return ret;}StrBlobPtr StrBlobPtr::operator-(int n) { auto ret = *this; ret.curr -= n; return ret;}
为什么不定义const版本的递增和递减运算符?
对于++和- -运算符,无论它是前缀版本还是后缀版本,都会改变对象本身的值,所以不能定义成const的。转载地址:http://atxmb.baihongyu.com/