您的位置:首页 > 编程语言 > C语言/C++

C++(28)自增/自减操作符

2015-08-08 19:55 501 查看


重载操作符与转换


--自增/自减操作符

引言:

自增,自减操作符经常由诸如迭代器这样的类实现,这样的类提供类似于指针的行为来访问序列中的元素。例如,可以定义一个类,该类指向一个数组并为该数组中的元素提供访问检查:

[cpp] view
plaincopy





class CheckedPtr

{

public:

//这个类没有默认构造函数,必须提供指向数组的指针。

/**构造函数的参数是两个指针:一个指向数组的开始,另一个指向数组的末端。

*构造函数用这两个指针初始化 beg 和 end

*并将 curr 初始化为指向第一个元素

*/

CheckedPtr(int *b,int *e):beg(b),end(e),curr(b){}



private:

/**三个成员

*beg:指向数组的第一个元素;

*end:指向数组的末端;

*curr:指向 CheckedPtr 对象当前引用的数组元素。

*/

int *beg;

int *end;

int *curr;

};

1、定义自增/自减操作符

【最佳实践】

C++语言不要求自增/自减操作符一定作为类的成员,但是,因为这些操作符改变操作对象的状态,所以更倾向于将它们作为成员!

2、定义前自增/自减操作符

前缀式操作符的声明看起来像这样:

[cpp] view
plaincopy





class CheckedPtr

{

public:

CheckedPtr &operator++();

CheckedPtr &operator--();

//AS Before

};

【最佳实践】

为了与内置类型一致,前缀操作符应该返回被增量或减量对象的引用。

自增操作符根据end检查curr,从而确保用户不能将curr增加到超过数组的末端。自减操作将curr减 1并检查是否会减到beg,如果curr增量到超过end或curr自减超过 beg就抛出一个out_of_range异常:

[cpp] view
plaincopy





CheckedPtr &CheckedPtr::operator++()

{

if (curr == end)

{

throw out_of_range("increment past the end of CheckedPtr");

}

++ curr;



return *this;

}



CheckedPtr &CheckedPtr::operator--()

{

if (curr == beg)

{

throw out_of_range("decrement past the beginning of CheckedPtr");

}

-- curr;



return *this;

}

3、区别操作符的前缀和后缀形式

后缀式操作符函数接受一个额外的(即:无用的)int型形参。使用后缀式操作符时,编译器提供0作为这个形参的实参。这个int形参的唯一目的就是使后缀函数与前缀函数区别开来

4、定义后缀式操作符

[cpp] view
plaincopy





class CheckedPtr

{

public:

CheckedPtr &operator++(int);

CheckedPtr &operator--(int);

//AS Before

};

【最佳实践】

为了与内置操作符一致,后缀式操作符应返回旧值[即:尚未自增或自减的值],并且,应作为值返回,而不是引用!

[cpp] view
plaincopy





CheckedPtr CheckedPtr::operator++(int)

{

CheckedPtr ret(*this);

++ *this;



return ret;

}



CheckedPtr CheckedPtr::operator--(int)

{

CheckedPtr ret(*this);

-- *this;



return ret;

}

必须保存对象在加1/减1之前的当前状态,当保存了当前状态的副本之后,操作符调用自己的前缀式操作符分别进行加1/减1:

[cpp] view
plaincopy





++*this; //-- *this;

调用这个对象自己的已经定义好了的前缀自增/自减操作符,那些关于curr是否处在beg和end范围之内的检查,以及是否抛出异常,则由它们代劳了O(∩_∩)O!

由于不使用int形参,所以对其没有命名

5、显式调用自增/自减操作符

如果想要使用函数调用来调用后缀式操作符,必须给出一个整型实参值:

[cpp] view
plaincopy





CheckedPtr parr(ia,ia+ sizeof(ia)/sizeof(*ia));

parr.operator++(); //显式调用前缀式

parr.operator++(0); //显式调用后缀式

所传的值通常被忽略,但是该值是必要的,用于通知编译器需要的是后缀式版本!

【最佳实践】

一般而言,最好前缀式和后缀式都定义,只定义前缀式或只定义后缀式的类,将会让习惯于使用两种形式的用户感到奇怪。

[cpp] view
plaincopy





//P449 习题14.23~26 着重复习前面几节的知识,由于知识点都比较简单,所以几乎没有注释...

#include <iostream>

#include <stdexcept>

using namespace std;



class CheckedPtr

{

friend bool operator==(const CheckedPtr &lhs,const CheckedPtr &rhs);

friend bool operator<(const CheckedPtr &lhs,const CheckedPtr &rhs);

friend bool operator>(const CheckedPtr &lhs,const CheckedPtr &rhs);



friend CheckedPtr operator+(const CheckedPtr &lhs,const size_t n);

friend CheckedPtr operator-(const CheckedPtr &lhs,const size_t n);

friend ptrdiff_t operator-(const CheckedPtr &lhs,const CheckedPtr &rhs);



public:

CheckedPtr(int *b,int *e):beg(b),end(e),curr(b) {}



CheckedPtr &operator++();

CheckedPtr &operator--();



CheckedPtr operator++(int);

CheckedPtr operator--(int);



int &operator[] (const size_t);

const int &operator[] (const size_t) const;



int &operator*();

const int &operator*() const;





private:

int *beg;

int *end;

int *curr;

};



CheckedPtr operator+(const CheckedPtr &rhs,const size_t n)

{

CheckedPtr ret(rhs);

ret.curr += n;

if (ret .curr > ret.end)

{

throw out_of_range("operator + out_of_range!");

}



return ret;

}



CheckedPtr operator-(const CheckedPtr &rhs,const size_t n)

{

CheckedPtr ret(rhs);

ret.curr -= n;

if (ret.curr < ret.beg)

{

throw out_of_range("operator - out_of_range!");

}



return ret;

}



ptrdiff_t operator-(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

if (!(lhs.beg == rhs.beg && lhs.end == rhs.end))

{

throw out_of_range("operator - out_of_range!");

}



return lhs.curr - rhs.curr;

}



inline

bool operator==(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return lhs.beg == rhs.beg && lhs.curr == rhs.curr && lhs.end == rhs.end;

}

inline

bool operator!=(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return !(lhs == rhs);

}



inline

bool operator<(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr < rhs.curr;

}

inline

bool operator>=(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return !(lhs < rhs);

}



inline

bool operator>(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr > rhs.curr;

}

inline

bool operator<=(const CheckedPtr &lhs,const CheckedPtr &rhs)

{

return !(lhs > rhs);

//OR: return lhs == rhs || lhs < rhs;

}



int &CheckedPtr::operator*()

{

if (curr == end)

{

throw out_of_range("Error Pointer!");

}



return *curr;

}



const int &CheckedPtr::operator*() const

{

if (curr == end)

{

throw out_of_range("Error Pointer!");

}



return *curr;

}



int &CheckedPtr::operator[](const size_t index)

{

if (beg + index >= end || beg + index < beg)

{

throw out_of_range("index: out_of_range!");

}

return *(beg + index);

}



const int &CheckedPtr::operator[](const size_t index) const

{

if (beg + index >= end || beg + index < beg)

{

throw out_of_range("index: out_of_range!");

}



return *(beg + index);

}



CheckedPtr &CheckedPtr::operator++()

{

if (curr == end)

{

throw out_of_range("increment past the end of CheckedPtr");

}

++ curr;



return *this;

}



CheckedPtr &CheckedPtr::operator--()

{

if (curr == beg)

{

throw out_of_range("decrement past the beginning of CheckedPtr");

}

-- curr;



return *this;

}



CheckedPtr CheckedPtr::operator++(int)

{

CheckedPtr ret(*this);

++ *this;



return ret;

}



CheckedPtr CheckedPtr::operator--(int)

{

CheckedPtr ret(*this);

-- *this;



return ret;

}



//测试

int main()

{

int ia[] = {10,8,6,4,2,0};

CheckedPtr flag(ia,ia + sizeof(ia)/sizeof(*ia));



for (CheckedPtr parr(ia,ia + sizeof(ia)/sizeof(*ia));

parr != flag + sizeof(ia)/sizeof(*ia); parr = parr + 2)

{

cout << *parr << endl;

}



for (CheckedPtr parr(ia,ia + sizeof(ia)/sizeof(*ia));

parr != flag + sizeof(ia)/sizeof(*ia); ++ parr)

{

cout << *parr << endl;

}



CheckedPtr parr1(ia,ia + sizeof(ia)/sizeof(*ia));

cout << endl << parr1[2] << endl;

cout << *parr1 << endl;



CheckedPtr parr2(ia,ia + sizeof(ia)/sizeof(*ia));

++ parr2;

cout << "parr1 <= parr2 ? " << (parr1 <= parr2) << endl;



return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: