引言:
自增, 自減操作符經常由諸如反覆運算器這樣的類實現, 這樣的類提供類似于指標的行為來訪問序列中的元素。 例如, 可以定義一個類, 該類指向一個陣列並為該陣列中的元素提供訪問檢查:
1、定義自增/自減操作符
【最佳實踐】
C++語言不要求自增/自減操作符一定作為類的成員, 但是, 因為這些操作符改變操作物件的狀態, 所以更傾向于將它們作為成員!
2、定義前自增/自減操作符
首碼式操作符的聲明看起來像這樣:
class CheckedPtr
{
public:
CheckedPtr &operator++();
CheckedPtr &operator--();
//AS Before
};
【最佳實踐】
為了與內置類型一致, 首碼操作符應該返回被增量或減量對象的引用。
自增操作符根據end檢查curr,從而確保用戶不能將curr增加到超過陣列的末端。 自減操作將curr減 1並檢查是否會減到beg,如果curr增量到超過end或curr自減超過 beg就拋出一個out_of_range異常:
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型形參。 使用尾碼式操作符時,
4、定義尾碼式操作符
class CheckedPtr
{
public:
CheckedPtr &operator++(int);
CheckedPtr &operator--(int);
//AS Before
};
最佳實踐】
為了與內置操作符一致, 尾碼式操作符應返回舊值[即:尚未自增或自減的值], 並且, 應作為值返回, 而不是引用!
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); //顯式調用尾碼式
所傳的值通常被忽略, 但是該值是必要的, 用於通知編譯器需要的是尾碼式版本!
【最佳實踐】
一般而言, 最好首碼式和尾碼式都定義, 只定義首碼式或只定義尾碼式的類, 將會讓習慣於使用兩種形式的用戶感到奇怪。
//P449 習題14.23~26 著重複習前面幾節的知識, 由於知識點都比較簡單, 所以幾乎沒有注釋...
#include
#include
usingnamespace std;
class CheckedPtr
{
friendbool operator==(const CheckedPtr &lhs,const CheckedPtr &rhs);
friendbool operator
friendbool operator>(const CheckedPtr &lhs,const CheckedPtr &rhs);
friend CheckedPtr operator+(const CheckedPtr &lhs,constsize_t n);
friend CheckedPtr operator-(const CheckedPtr &lhs,constsize_t n);
friendptrdiff_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[] (constsize_t);
constint &operator[] (constsize_t) const;
int &operator*();
constint &operator*() const;
private:
int *beg;
int *end;
int *curr;
};
CheckedPtr operator+(const CheckedPtr &rhs,constsize_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,constsize_t n)
{
CheckedPtr ret(rhs);
ret.curr -= n;
if (ret.curr
{
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
{
return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr
}
inline
bool operator>=(const CheckedPtr &lhs,const CheckedPtr &rhs)
{
return !(lhs
}
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
{
return !(lhs > rhs);
//OR: return lhs == rhs || lhs
}
int &CheckedPtr::operator*()
{
if (curr == end)
{
throw out_of_range("Error Pointer!");
}
return *curr;
}
constint &CheckedPtr::operator*() const
{
if (curr == end)
{
throw out_of_range("Error Pointer!");
}
return *curr;
}
int &CheckedPtr::operator[](constsize_t index)
{
if (beg + index >= end || beg + index
{
throw out_of_range("index: out_of_range!");
}
return *(beg + index);
}
constint &CheckedPtr::operator[](constsize_t index) const
{
if (beg + index >= end || beg + index
{
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
}
for (CheckedPtr parr(ia,ia + sizeof(ia)/sizeof(*ia));
parr != flag + sizeof(ia)/sizeof(*ia); ++ parr)
{
cout
}
CheckedPtr parr1(ia,ia + sizeof(ia)/sizeof(*ia));
cout
cout
CheckedPtr parr2(ia,ia + sizeof(ia)/sizeof(*ia));
++ parr2;
cout
return 0;
}