1.為啥要重載操作符:
通過(guò)重載操作符,程序員可以針對(duì)“類”類型的操作數(shù)定義不同的操作符版本。良好的操作符定義可以使class類型的使用想內(nèi)置類型一樣直觀簡(jiǎn)潔,使用重定義的操作符而不是命名函數(shù)使得程序可以用表達(dá)式代替函數(shù)調(diào)用,使程序編寫和閱讀更容易~
2.哪些不能重載
:: .* . ?: 這些不能重載
3.需要注意的地方:
重載必須有一個(gè)class類型的操作數(shù),短路求值失去,
重載操作符和內(nèi)置操作符結(jié)合型相同,優(yōu)先級(jí)操作數(shù)個(gè)數(shù)均相同
不要重載一些含有內(nèi)置定義的操作符 & , && || 這些
·賦值(=)下標(biāo)(【】)調(diào)用 (())和成員訪問(wèn)操作符必須定義為成員
·對(duì)稱的操作符一般定義為普通非成員函數(shù)
++ -- 一般設(shè)置為成員函數(shù) ,因?yàn)榭赡芨淖儗?duì)象狀態(tài)
4.定義輸入輸出操作符
io操作符只能重載為非成員函數(shù),否則做操作符只能是對(duì)象成員 用法變成了 object<<cin 不符合我們的習(xí)慣,經(jīng)常把他們?cè)O(shè)置成為友元,因?yàn)榭赡苡|及私有變量。
輸入必須加入文件結(jié)束和輸入錯(cuò)誤的錯(cuò)誤處理
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;
}
如果輸入失敗,調(diào)用默認(rèn)構(gòu)造函數(shù)恢復(fù)對(duì)象狀態(tài)。
5.算術(shù)運(yùn)算符和關(guān)系運(yùn)算符
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;
}
一般算術(shù)運(yùn)算符設(shè)置為非成員函數(shù),與內(nèi)置運(yùn)算符對(duì)應(yīng),選擇返回value 而不是引用。賦值運(yùn)算符重載為成員函數(shù),并用它來(lái)實(shí)現(xiàn)算術(shù)運(yùn)算符,這樣算術(shù)運(yùn)算符不用friend
相等運(yùn)算符和不等運(yùn)算符一般成對(duì)出現(xiàn),且用一個(gè)實(shí)現(xiàn)另一個(gè)
關(guān)系運(yùn)算符 == != > < 一般重載成非成員函數(shù)
6.賦值操作符
必須為成員函數(shù) (=號(hào))
=和+= -= 一般都需要返回左操作數(shù)的引用
Sales_item& operator = (string is){
isbn = is;
return *this;
}
6.下標(biāo)操作符
必須為類成員函數(shù) 返回引用使其可以在賦值操作的任意一邊
一般定義一種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.成員訪問(wèn)操作符
-> 一般要求重載為成員運(yùn)算符,*沒(méi)有要求 ,但成員比較常見~~~
例子:auto-ptr~~~~
ScreenPtr 的用戶將會(huì)傳遞一個(gè)指針,該指針指向動(dòng)態(tài)分配的 Screen,ScreenPtr 類將擁有該指針,并安排在指向基礎(chǔ)對(duì)象的最后一個(gè) ScreenPtr 消失時(shí)刪除基礎(chǔ)對(duì)象。另外,不用為 ScreenPtr 類定義默認(rèn)構(gòu)造函數(shù)。因此,我們知道一個(gè) ScreenPtr 對(duì)象將總是指向一個(gè) Screen 對(duì)象,不會(huì)有未綁定的 ScreenPtr,這一點(diǎn)與內(nèi)置指針不同。應(yīng)用程序可以使用 ScreenPtr 對(duì)象而無(wú)須首先測(cè)試它是否指向一個(gè) Screen 對(duì)象。
// 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
};
解引用操作符是個(gè)一元操作符。在這個(gè)類中,解引用操作符定義為成員,因此沒(méi)有顯式形參,該操作符返回對(duì) ScreenPtr 所指向的 Screen 的引用。
箭頭操作符不接受顯式形參。point->action(); 等價(jià)于 (point->action)();
可以這樣使用 ScreenPtr 對(duì)象訪問(wèn) Screen 對(duì)象的成員:
ScreenPtr p(&myScreen); // copies the underlying Screen
p->display(cout);
因?yàn)?p 是一個(gè) ScreenPtr 對(duì)象,p->display 的含義與對(duì) (p.operator->())->display 求值相同。對(duì) p.operator->() 求值將調(diào)用 ScreenPtr 類的 operator->,它返回指向 Screen 對(duì)象的指針,該指針用于獲取并運(yùn)行 ScreenPtr 所指對(duì)象的 display 成員。
重載箭頭操作符必須返回指向類類型的指針,或者返回定義了自己的箭頭操作符的類類型對(duì)象。
6.自增自減操作符
一般重載為成員函數(shù),為了與內(nèi)置類型一致,前置操作符返回運(yùn)算結(jié)果引用,后置操作符返回運(yùn)算前的值,value not ref ,為了區(qū)分,后置操作符提供了一個(gè)實(shí)參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 用前置實(shí)現(xiàn)它,不用判斷出界了
return ret; // return saved state
}
顯式調(diào)用:
CheckedPtr parr(ia, ia + size); // iapoints to an array of ints
parr.operator++(0); // call postfix operator++
parr.operator++(); // call prefix operator++
7 調(diào)用操作符和函數(shù)對(duì)象
struct absInt {
int operator() (int val) {
return val < 0 ? -val : val;
}
};
通過(guò)為類類型的對(duì)象提供一個(gè)實(shí)參表而使用調(diào)用操作符,所用的方式看起來(lái)像一個(gè)函數(shù)調(diào)用:
int i = -42;
absInt absObj; // object that defines function call operator
unsigned int ui = absObj(i); // calls absInt::operator(int)
函數(shù)調(diào)用操作符必須聲明為成員函數(shù)。一個(gè)類可以定義函數(shù)調(diào)用操作符的多個(gè)版本,由形參的數(shù)目或類型加以區(qū)別。
定義了調(diào)用操作符的類,其對(duì)象常稱為函數(shù)對(duì)象,即它們是行為類似函數(shù)的對(duì)象。
函數(shù):
// determine whether a length of a given word is 6 or more
bool GT6(const string &s)
{
return s.size() >= 6;
}
函數(shù)對(duì)象:
// 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;
函數(shù)對(duì)象的便捷性】
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
函數(shù)適配器:
banding器,它通過(guò)將一個(gè)操作數(shù)綁定到給定值而將二元函數(shù)對(duì)象轉(zhuǎn)換為一元函數(shù)對(duì)象
求反器是一種函數(shù)適配器,它將謂詞函數(shù)對(duì)象的真值求反。標(biāo)準(zhǔn)庫(kù)定義了兩個(gè)求反器:not1 和 not2 分別求反一元二元對(duì)象
8。實(shí)參匹配和轉(zhuǎn)換(俺來(lái)看重載操作符的原因啊,,,)
轉(zhuǎn)換操作符是一種特殊的類成員函數(shù)。它定義將類類型值轉(zhuǎn)變?yōu)槠渌愋椭档霓D(zhuǎn)換。轉(zhuǎn)換操作符在類定義體內(nèi)聲明,在保留字 operator 之后跟著轉(zhuǎn)換的目標(biāo)類型:
轉(zhuǎn)換函數(shù)采用如下通用形式:
operator type();
轉(zhuǎn)換函數(shù)必須是成員函數(shù),不能指定返回類型,并且形參表必須為空。
雖然轉(zhuǎn)換函數(shù)不能指定返回類型,但是每個(gè)轉(zhuǎn)換函數(shù)必須顯式返回一個(gè)指定類型的值。例如,operator int 返回一個(gè) int 值;如果定義 operator Sales_item,它將返回一個(gè) Sales_item 對(duì)象,諸如此類。
轉(zhuǎn)換函數(shù)一般不應(yīng)該改變被轉(zhuǎn)換的對(duì)象。因此,轉(zhuǎn)換操作符通常應(yīng)定義為 const 成員。
只要存在轉(zhuǎn)換,編譯器將在可以使用內(nèi)置轉(zhuǎn)換的地方自動(dòng)調(diào)用它
In expressions:
在表達(dá)式中:
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:
將實(shí)參傳給函數(shù)或從函數(shù)返回值:
int calc(int);
SmallInt si;
int i = calc(si); // convert si to int and call calc
As operands to overloaded operators:
作為重載操作符的操作數(shù):
// convert si to int then call opeator<< on the int value
cout << si << endl;
In an explicit cast:
在顯式類型轉(zhuǎn)換中:
int ival;
SmallInt si = 3.541; //
instruct compiler to cast si to int
ival = static_cast<int>(si) + 3;
類類型轉(zhuǎn)換之后不能再跟另一個(gè)類類型轉(zhuǎn)換。如果需要多個(gè)類類型轉(zhuǎn)換,則代碼將出錯(cuò)。(指的是不能連續(xù)兩個(gè)自定義的類型轉(zhuǎn)換,但是內(nèi)置類型轉(zhuǎn)換可以的)
還有一部分是實(shí)參匹配和轉(zhuǎn)換 ,沒(méi)時(shí)間了 以后再看~~~~