1.為啥要重載操作符:
通過重載操作符,程序員可以針對“類”類型的操作數定義不同的操作符版本。良好的操作符定義可以使class類型的使用想內置類型一樣直觀簡潔,使用重定義的操作符而不是命名函數使得程序可以用表達式代替函數調用,使程序編寫和閱讀更容易~
2.哪些不能重載
:: .* . ?: 這些不能重載
3.需要注意的地方:
重載必須有一個class類型的操作數,短路求值失去,
重載操作符和內置操作符結合型相同,優先級操作數個數均相同
不要重載一些含有內置定義的操作符 & , && || 這些
·賦值(=)下標(【】)調用 (())和成員訪問操作符必須定義為成員
·對稱的操作符一般定義為普通非成員函數
++ -- 一般設置為成員函數 ,因為可能改變對象狀態
4.定義輸入輸出操作符
io操作符只能重載為非成員函數,否則做操作符只能是對象成員 用法變成了 object<<cin 不符合我們的習慣,經常把他們設置成為友元,因為可能觸及私有變量。
輸入必須加入文件結束和輸入錯誤的錯誤處理
istream&
operator>>(istream& in, Sales_item& s)
{
double price;
in >> s.isbn >> s.units_sold >> price;
// check that the inputs succeeded
if (in)
s.revenue = s.units_sold * price;
else
s = Sales_item(); // input failed: reset object to default state
return in;
}
如果輸入失敗,調用默認構造函數恢復對象狀態。
5.算術運算符和關系運算符
Sales_item& operator -=(const Sales_item& item){
units_sold-=item.units_sold;
revenue-=item.revenue;
return *this;
}
Sales_item operator - (const Sales_item& lhs,const Sales_item& rhs){
Sales_item res(lhs);
res+=rhs;
return res;
}
一般算術運算符設置為非成員函數,與內置運算符對應,選擇返回value 而不是引用。賦值運算符重載為成員函數,并用它來實現算術運算符,這樣算術運算符不用friend
相等運算符和不等運算符一般成對出現,且用一個實現另一個
關系運算符 == != > < 一般重載成非成員函數
6.賦值操作符
必須為成員函數 (=號)
=和+= -= 一般都需要返回左操作數的引用
Sales_item& operator = (string is){
isbn = is;
return *this;
}
6.下標操作符
必須為類成員函數 返回引用使其可以在賦值操作的任意一邊
一般定義一種const 返回常量引用 一種not const 引用
class Foo {
public:
int &operator[] (const size_t);
const int &operator[] (const size_t) const;
// other interface members
private:
vector<int> data;
// other member data and private utility functions
};
int& Foo::operator[] (const size_t index)
{
return data[index]; // no range checking on index
}
const int& Foo::operator[] (const size_t index) const
{
return data[index]; // no range checking on index
}
pari<string,string>& operator[] (const vector< pair<string,string>* > ::size_type index){
return *wait_list.at(index);//使用at判斷是否越界
}
6.成員訪問操作符
-> 一般要求重載為成員運算符,*沒有要求 ,但成員比較常見~~~
例子:auto-ptr~~~~
ScreenPtr 的用戶將會傳遞一個指針,該指針指向動態分配的 Screen,ScreenPtr 類將擁有該指針,并安排在指向基礎對象的最后一個 ScreenPtr 消失時刪除基礎對象。另外,不用為 ScreenPtr 類定義默認構造函數。因此,我們知道一個 ScreenPtr 對象將總是指向一個 Screen 對象,不會有未綁定的 ScreenPtr,這一點與內置指針不同。應用程序可以使用 ScreenPtr 對象而無須首先測試它是否指向一個 Screen 對象。
// private class for use by ScreenPtr only 私有類,
class ScrPtr {
friend class ScreenPtr;
Screen *sp;
size_t use;
ScrPtr(Screen *p): sp(p), use(1) { }
~ScrPtr() { delete sp; }
};
/*
* smart pointer: Users pass to a pointer to a dynamically allocated Screen, which
* is automatically destroyed when the last ScreenPtr goes away
*/
class ScreenPtr {
public:
// no default constructor: ScreenPtrs must be bound to an object
ScreenPtr(Screen *p): ptr(new ScrPtr(p)) { }
// copy members and increment the use count
ScreenPtr(const ScreenPtr &orig):
ptr(orig.ptr) { ++ptr->use; }
ScreenPtr& operator=(const ScreenPtr&);
// if use count goes to zero, delete the ScrPtr object
~ScreenPtr() { if (--ptr->use == 0) delete ptr; }
private:
ScrPtr *ptr; // points to use-counted ScrPtr class
};
指針支持的基本操作有解引用操作和箭頭操作。我們的類可以這樣定義這些操作:
class ScreenPtr {
public:
// constructor and copy control members as before
Screen &operator*() { return *ptr->sp; }
Screen *operator->() { return ptr->sp; }
const Screen &operator*() const { return *ptr->sp; }
const Screen *operator->() const { return ptr->sp; }
private:
ScrPtr *ptr; // points to use-counted ScrPtr class
};
解引用操作符是個一元操作符。在這個類中,解引用操作符定義為成員,因此沒有顯式形參,該操作符返回對 ScreenPtr 所指向的 Screen 的引用。
箭頭操作符不接受顯式形參。point->action(); 等價于 (point->action)();
可以這樣使用 ScreenPtr 對象訪問 Screen 對象的成員:
ScreenPtr p(&myScreen); // copies the underlying Screen
p->display(cout);
因為 p 是一個 ScreenPtr 對象,p->display 的含義與對 (p.operator->())->display 求值相同。對 p.operator->() 求值將調用 ScreenPtr 類的 operator->,它返回指向 Screen 對象的指針,該指針用于獲取并運行 ScreenPtr 所指對象的 display 成員。
重載箭頭操作符必須返回指向類類型的指針,或者返回定義了自己的箭頭操作符的類類型對象。
6.自增自減操作符
一般重載為成員函數,為了與內置類型一致,前置操作符返回運算結果引用,后置操作符返回運算前的值,value not ref ,為了區分,后置操作符提供了一個實參0;
// prefix: return reference to incremented/decremented object
CheckedPtr& CheckedPtr::operator++()
{
if (curr == end)
throw out_of_range
("increment past the end of CheckedPtr");
++curr; // advance current state
return *this;
}
CheckedPtr CheckedPtr::operator++(int)
{
// no check needed here, the call to prefix increment will do the check
CheckedPtr ret(*this); // save current value
++*this; // advance one element, checking the increment 用前置實現它,不用判斷出界了
return ret; // return saved state
}
顯式調用:
CheckedPtr parr(ia, ia + size); // iapoints to an array of ints
parr.operator++(0); // call postfix operator++
parr.operator++(); // call prefix operator++
7 調用操作符和函數對象
struct absInt {
int operator() (int val) {
return val < 0 ? -val : val;
}
};
通過為類類型的對象提供一個實參表而使用調用操作符,所用的方式看起來像一個函數調用:
int i = -42;
absInt absObj; // object that defines function call operator
unsigned int ui = absObj(i); // calls absInt::operator(int)
函數調用操作符必須聲明為成員函數。一個類可以定義函數調用操作符的多個版本,由形參的數目或類型加以區別。
定義了調用操作符的類,其對象常稱為函數對象,即它們是行為類似函數的對象。
函數:
// determine whether a length of a given word is 6 or more
bool GT6(const string &s)
{
return s.size() >= 6;
}
函數對象:
// determine whether a length of a given word is longer than a stored bound
class GT_cls {
public:
GT_cls(size_t val = 0): bound(val) { }
bool operator()(const string &s)
{ return s.size() >= bound; }
private:
std::string::size_type bound;
};
for (size_t i = 0; i != 11; ++i)
cout << count_if(words.begin(), words.end(), GT(i))
<< " words " << i
<< " characters or longer" << endl;
函數對象的便捷性】
plus<int> intAdd; // function object that can add two int values
negate<int> intNegate; // function object that can negate an int value
// uses intAdd::operator(int, int) to add 10 and 20
int sum = intAdd(10, 20); // sum = 30
// uses intNegate::operator(int) to generate -10 as second parameter
// to intAdd::operator(int, int)
sum = intAdd(10, intNegate(10)); // sum = 0
函數適配器:
banding器,它通過將一個操作數綁定到給定值而將二元函數對象轉換為一元函數對象
求反器是一種函數適配器,它將謂詞函數對象的真值求反。標準庫定義了兩個求反器:not1 和 not2 分別求反一元二元對象
8。實參匹配和轉換(俺來看重載操作符的原因啊,,,)
轉換操作符是一種特殊的類成員函數。它定義將類類型值轉變為其他類型值的轉換。轉換操作符在類定義體內聲明,在保留字 operator 之后跟著轉換的目標類型:
轉換函數采用如下通用形式:
operator type();
轉換函數必須是成員函數,不能指定返回類型,并且形參表必須為空。
雖然轉換函數不能指定返回類型,但是每個轉換函數必須顯式返回一個指定類型的值。例如,operator int 返回一個 int 值;如果定義 operator Sales_item,它將返回一個 Sales_item 對象,諸如此類。
轉換函數一般不應該改變被轉換的對象。因此,轉換操作符通常應定義為 const 成員。
只要存在轉換,編譯器將在可以使用內置轉換的地方自動調用它
In expressions:
在表達式中:
SmallInt si;
double dval;
si >= dval // si converted to int and then convert to double
In conditions:
在條件中:
if (si) // si converted to int and then convert to bool
When passing arguments to or returning values from a function:
將實參傳給函數或從函數返回值:
int calc(int);
SmallInt si;
int i = calc(si); // convert si to int and call calc
As operands to overloaded operators:
作為重載操作符的操作數:
// convert si to int then call opeator<< on the int value
cout << si << endl;
In an explicit cast:
在顯式類型轉換中:
int ival;
SmallInt si = 3.541; //
instruct compiler to cast si to int
ival = static_cast<int>(si) + 3;
類類型轉換之后不能再跟另一個類類型轉換。如果需要多個類類型轉換,則代碼將出錯。(指的是不能連續兩個自定義的類型轉換,但是內置類型轉換可以的)
還有一部分是實參匹配和轉換 ,沒時間了 以后再看~~~~