http://hi.baidu.com/xiaoduo170/blog/item/9ae4cf51ae739110377abe16.html+ - * / % ^ & | ~ ! = > < += -= *= /= %= ^= &= |= >> << >>= <<= == != >= <= && || ++ -- ->* , -> [] () operator new operator new[] operator delete operator delete [] II.不能重載的操作符:: . .* ? : sizeof typeid new delete static_cast dynamic_cast const_cast reinterpret_cast III.基本規則1.一元操作符可以是不帶參數的成員函數[1]或帶一個(gè)參數的非成員函數[1]。2.二元操作符可以是帶一個(gè)參數的成員函數[1]或帶兩個(gè)參數的非成員函數[1]。3.operator=、operator[]、operator()、operator->只能定義為成員函數[1]。4.operator->的返回值必須是一個(gè)指針或能使用->的對象。5.重載 operator++ 和 operator-- 時(shí)帶一個(gè) int 參數表示后綴,不帶參數表示前綴。6.除 operator new 和 operator delete 外,重載的操作符參數中至少要有一個(gè)非內建數據類(lèi)型。7.x@y 搜索范圍為:x 成員函數--> 全局函數/X所在名字空間中的函數/Y所在名字空間中的函數/X的友元函 數/Y的友元函數。8.重載的的操作符應盡量模擬操作符對內建類(lèi)型的行為。二、使用重載I.操作符重載的一些建議 1.只將會(huì )改變第一個(gè)參數的值的操作符(如: +=)定義為成員函數,而將返回一個(gè)新對象的操作符(如: +)定義為非成員函數(并使用 += 來(lái)實(shí)現)。 2.只有非成員函數才能在左參數上實(shí)施性別轉換,如果需要進(jìn)行轉換則應將操作符定義為非成員函數。 3.對一元操作符, 為避免隱式轉換最好將其重載為成員函數。 4.對二元操作符, 為能在左操作數上能進(jìn)行和右操作數一樣的隱式轉換, 最好將其重載為非成員函數。 5.為了遵照使用習慣,operator>>、operator<< 應定義為非成員函數。 6.重載 operator[] 之類(lèi)的操作符, 應盡量提供 const 版本和非 const 版本。 7.關(guān)于將操作符定義為成員或非成員可參考以下建議:操作符 建 議 所有一元操作符 成員 = () [] -> 必須為成員 += -= /= *= ^= &= != %= >>= <<= 成員 其它二元操作符 非成員 8.如果默認操作符已經(jīng)可以施用于你的型別上, 則應盡量避免重載此操作符. 如 operator, 、operator&(取地址) 等等.II. 重載 operator new 1.為什么要重載 operator new ?[效率問(wèn)題] 通常系統默認提供的分配器速度極慢, 而且分配小型對象時(shí)空間浪費嚴重.[改變行為] 默認的分配器失敗時(shí)會(huì )拋出異常, 或許你想改變這種行為. 2. operator new 的行為[區分三個(gè)不同的 new] new 操作符(new 表達式, new operator, new expression): 通常我們調用 X * pX = new X 時(shí)使用的就是這個(gè)操作符, 它由語(yǔ)言?xún)冉? 不能重載, 不能改變其行為. 它包括分配內存的 operator new 和調用構造函數的 placement new. operator new :opeator new 是一個(gè)函數, void * operator new(size_t size) . 它分配指定大小的內存, 可以被重載, 可以添加額外的參數, 但第一個(gè)參數必須為 size_t. operator new 除了被 new operator 調用外也可以直接被調用: void * rawMem = operator new(sizeof(X)). placement new : placement new 在一塊指定的內存上使用構造函數, 包含頭文件 <new> 之后也可以直接使用 placement new: X * pX = new (rawMem) X. [2] 與 new operator 類(lèi)似, 對于 delete operator, 也存在 operator delete: void operator delete(void *), 析構方法 pX->~X().[operator new 的錯誤處理] 默認的 operator new 在內存分配失敗時(shí)將會(huì )拋出 std::bad_alloc 異常; nothrow new [3] (X * pX = new (nothrow) X) 在內存分配失敗時(shí)將會(huì )返回 0 . 這種行為可以通過(guò)設置 new-handler 來(lái)改變. new-handler 是一個(gè)回調函數指針, typedef void(*new_handler)(void). 通過(guò) set_new_handler(new_handler) 函數設置回調句柄后, 如果分配內存失敗, operator new 將會(huì )不斷的調用 new-handler 函數, 直到找到足夠的內存為止. 為了避免死循環(huán), new-handler 函數必須具備以下行為之一: (1).找到可用的內存. (2).安裝其它的 new-handler 函數. (3).卸除 new-handler, 即 set_new_hanlder(0), 這樣下此循環(huán)將恢復默認行為拋出異?;蚍祷?0. (4).拋出異常. (5).保存錯誤日志, 退出程序. 3.準備重載 operator new 重載 operator new 時(shí)需要兼容默認的 operator new 錯誤處理方式. 另外, C++ Standard 規定當要求的內存為 0 byte 時(shí)也應該返回有效的內存地址. 所以 operator new 的重載實(shí)現應大致如下:void * ... operator new(size_t size ... ){ if(size == 0) size = 1; while(1) { ... // allocate memery if(allocate sucessfull) return ... // return the pointer. new_handler curhandler = set_new_handler(0); set_new_handler(curhandler); // get current new handler if(curhandler == 0) (*curhandler)(); else throw std::bad_alloc(); }} 重載 operator delete 簡(jiǎn)單許多, 只需注意 C++ Standard 要求刪除一個(gè) NULL 是安全的即可. 4.重載 operator new opeator new 的重載和其它操作符大不相同.首先, 即使你不重載, 默認的 operator new 也可施用于你的自定義型別上(operator, 也具有此特性), 而其它操作符如果不進(jìn)行重載就無(wú)法使用. 其次, 其它重載其它操作符時(shí)參數個(gè)數都是固定的, 而 operator new 的參數個(gè)數是可以任意的, 只需要保證第一個(gè)參數為 size_t, 返回類(lèi)型為 void * 即可, 而且其重載的參數類(lèi)型也不必包含自定義類(lèi)型. 更一般的說(shuō), operator new 的重載更像是一個(gè)函數的重載, 而不是一個(gè)操作符的重載. [★ 用不同的參數重載 operator new] 通過(guò)使用不同的參數類(lèi)型, 可以重載 operator new, 例如 : void * operator new(size_t size, int x, int y, int z){ ...}X * pX = new (1, 2, 3) X; 你還可以為 operator new 的重載使用默認值, 其原則和普通函數重載一樣, 只要不造成和已存在的形式發(fā)生沖突即可. 可能你已經(jīng)想到了, 你甚至還可以在 operator new 中使用不定參數, 如果你真的需要的話(huà). void * operator new(size_t size, int x, int y = 0, int z = 0){ ...}X * pX = new (10) X;Y * pY = new (10, 10) Y;Z * pZ = new (10, 10, 10) Z;...void * operator new(size_t size, ...)... 在全局空間中也可直接重載 void * operator new(size_t size) 函數, 這將改變所有默認的 new 操作符的行為, 不建議使用.[★ 重載 class 專(zhuān)屬的 operator new] 為某個(gè) class 重載 operator new 時(shí)必須定義為類(lèi)的靜態(tài)函數[4], 因為 operator new 會(huì )在類(lèi)的對象被構建出來(lái)之前調用. 即是說(shuō)調用 operator new 的時(shí)候還不存在 this 指針, 因此重載的 operator new 必須為靜態(tài)的. 當然在類(lèi)中重載 operator new 也可以添加額外的參數, 并可以使用默認值.另外, 和普通函數一樣, operator new 也是可以繼承的. class X{...static void * operator new(size_t size); // ... (1)static void * operator new(size_t size, int); // ... (2)};class Y : public X{...};class Z : public X{...static void * operator new(size_t size); // ... (3)};X * pX1 = new X; // call (1)X * pX2 = ::new X; // call default operator newX * pX3 = new (0) X; // call (2)Y * pY1 = new Y; // call (1)Z * pZ1 = new Z; // call (3)Z * pZ2 = ::new Z; // call default operator newZ * pZ3 = X::new Z; // error, no way to call (1)Z * pZ4 = new (0) Z; // error, no way to call (2) 5.重載 operator delete 如果你重載了一個(gè) operator new, 記得一定要在相同的范圍內重載 operator delete. 因為你分配出來(lái)的內存只有你自己才知道如何釋放. 如果你忘記了, 編譯器不會(huì )給你任何提示, 它將會(huì )使用默認的 operator delete 來(lái)釋放內存. 這種忘記的代價(jià)是慘重的, 你得時(shí)刻在寫(xiě)下 operator new 的同時(shí)寫(xiě)下 operator delete. 如果在類(lèi)中使用 operator delete, 也必須將其聲明為靜態(tài)函數. 因為調用 operator delete 時(shí)對象已經(jīng)被析構掉了. operator delete 的重載可以有兩種形式:(1) void operator delete(void * mem)(2) void operator delete(void * mem, size_t size) 并且這兩種形式的 operator delete 可以同時(shí)存在, 當調用 delete px 時(shí), 如果 (1) 式存在的話(huà)將調用 (1) 式. 只有在 (1) 式不存在時(shí)才會(huì )調用 (2) 式. 對第 (2) 種形式的 operator delete, 如果用基類(lèi)指針刪除派生類(lèi)對象, 而基類(lèi)的析構函數沒(méi)有虛擬的時(shí)候, size 的值可能是錯誤的.三、重載參考- const Carrot operator+(const Carrot& lhs, const Carrot& rhs) { Carrot result = lhs; return result += rhs; } 【注】1. 如果可能, 應考慮使用 operator+= 來(lái)實(shí)現 operator+ . 2. operator+ 不能返回引用, 應返回值類(lèi)型. 3. 為了阻止形如 (a + b) = c 的調用, 應將返回值聲明為 const .· const Carrot operator-(const Carrot& lhs, const Carrot& rhs)- const Carrot operator*(const Carrot& lhs, const Carrot& rhs) { ... } 【注】1. operator* 還可以重載為提領(lǐng)操作符.· const Carrot operator/(const Carrot& lhs, const Carrot& rhs)· const Carrot operator%(const Carrot& lhs, const Carrot& rhs)· const Carrot operator^(const Carrot& lhs, const Carrot& rhs)- const Carrot operator&(const Carrot& lhs, const Carrot& rhs) { ... } 【注】1. operator& 還可以重載為取地址操作符.· const Carrot operator|(const Carrot& lhs, const Carrot& rhs)- const Carrot Carrot::operator-() const { Carrot result = (*this); ... // chang the value to negative return result; } 【注】1. 一元操作符, 取負.· const Carrot Carrot::operator~() const· bool Carrot::operator!() const· bool operator>(const Carrot& lhs, const Carrot& rhs)· bool operator<(const Carrot& lhs, const Carrot& rhs)- Carrot& Carrot::operator=(const Carrot& rhs) { if(this == &rhs) return *this; // may be (*this) == rhs if needs. Barley::operator=(rhs); // if Carrot derived from Barley ... // assignments every memeber of Carrot. return *this; } 【注】1. 為了實(shí)現形如 x=y=z=0 的串聯(lián)賦值操作, operator= 必須傳回 *this 的非常量引用. 2. 在賦值時(shí)應注意檢查是否為自賦值 ( a = a ).- Carrot& Carrot::operator+=(const Carrot& rhs) { ... return *this; } 【注】1. C++ 允許 (x += 1) = 0 形式的賦值操作, operator+= 必須傳回 *this 的非常量引用.· Carrot& Carrot::operator-=(const Carrot& rhs)· Carrot& Carrot::operator*=(const Carrot& rhs)· Carrot& Carrot::operator/=(const Carrot& rhs)· Carrot& Carrot::operator%=(const Carrot& rhs)· Carrot& Carrot::operator^=(const Carrot& rhs)· Carrot& Carrot::operator&=(const Carrot& rhs)· Carrot& Carrot::operator|=(const Carrot& rhs)- istream& operator>>(istream& _IStr, Carrot& rhs) { ... return _IStr; } 【注】1. 為了遵照使用習慣(cin>>x 而不是 x>>cin), 對流操作的 operator>> 應為非成員函數.- ostream& operator<<(ostream& _OStr, const Carrot& rhs) { ... return _OStr; }- const Carrot operator>>(const Carrot& lhs, int rhs) { Carrot result = lhs; ... return result; } 【注】1. 移位操作的重載方式.· const Carrot operator<<(const Carrot& lhs, int rhs)- Carrot& Carrot::operator>>=(int rhs) { ... return *this; } 【注】1. 移位操作.· Carrot& Carrot::operator<<=(int rhs)- bool operator==(const Carrot& lhs, const Carrot& rhs) { ... }· bool operator!=(const Carrot& lhs, const Carrot& rhs)· bool operator>=(const Carrot& lhs, const Carrot& rhs)· bool operator<=(const Carrot& lhs, const Carrot& rhs)- bool operator&&(const Carrot& lhs, const Carrot& rhs) X { ... } 【注】1. 基于以下原因, 你應該避免重載 operator&& 和 operator|| : (1). && 和 || 是一個(gè)邏輯操作符, 只對 bool 型別有才有明確的語(yǔ)意. (2). 重載的 operator&& 和 operator|| 無(wú)法模擬操作符默認的驟死式語(yǔ)義[5]. (3). 你無(wú)法保證重載后操作符的參數求值次序(C++ Stand 保證了默認的 && 和 || 按從左到右求值). 2.自定義型別可以考慮提供到 bool 的轉型操作來(lái)支持此操作符.· bool operator||(const Carrot& lhs, const Carrot& rhs) X - Carrot& Carrot::operator++() { (*this) += 1; // or other implement return *this;} 【注】1. 前置操作(prefix): ++carrot- const Carrot Carrot::operator++(int) { Carrot oldValue = *this; ++(*this); return oldValue;} 【注】1. 后置操作(postfix): carrot++ 調用時(shí)編譯器自動(dòng)生成一個(gè) 0 作為參數. 2. 為了禁止 carrot++++ 操作, 返回值應為 const. 3. 從實(shí)現和參數可以看出,后置操作的效率遠遠低于前置操作, 所以如非必要盡量使用前置操作. 4. 為了保證遞增行為一致, 并便于維護后置操作最好使用前置操作來(lái)完成遞增行為.· Carrot& Carrot::operator--()· const Carrot Carrot::operator--(int)- const Carrot operator,(const Carrot& lhs, const Carrot& rhs) X { ...} 【注】1. 基于以下原因, 你應該避免重載 operator, : (1). 即使沒(méi)有重載, 默認,號操作符也可以施用于自定義型別上. (2). C++ 保證 , 操作符的求值是從左到右的, 而重載后無(wú)法保證此行為.- const PMFC Carrot::operator->*(ReturnType (T::*pmf)()) const { ...} 【注】1. operator->* 重載比較少見(jiàn), 有興趣可參考Implementing operator->* for Smart Pointers.- const Carrot* Carrot::operator&() const X { ...} 【注】1. 你應該盡量避免重載取地址操作符.- Coca& Carrot::operator*() { ...} 【注】1. 重載提領(lǐng)操作符應提供 const 版和非 const 版.· const Coca& Carrot::operator*() const- Coca* Carrot::operator->() { ...} 【注】1. 重載 operator-> 應提供 const 版和非 const 版. 2. operator-> 的返回值必須為一個(gè)指針或可以應用 -> 操作的類(lèi)型. 3. 如果 operator-> 的返回的不是一個(gè)指針, C++ 會(huì )繼續在返回類(lèi)型上應用 -> 直到得到一個(gè)指針為止.· const Coca* Carrot::operator->() const- Coca& Carrot::operator[](KeyType index) { ...} 【注】1. operator[] 應提供 const 版本和非 const 版. 2. KeyType 可以為任意類(lèi)型, 但通常為 int 型.· const Coca& Carrot::operator[](KeyType index) const - AnyType Carrot::operator()(...) { ...} 【注】1. operator () 重載的是函數運算符, 改變表達式優(yōu)先級的 () 是不能重載的. 2. 重載了 operator() 的對象被成為仿函數, 使用方法和函數指針類(lèi)似.- static void* Carrot::operator new(size_t size, ...) { if(size == 0) size = 1; while(1) { ... // allocate memery if(allocate sucessfull) return ... // return the pointer. new_handler curhandler = set_new_handler(0); set_new_handler(curhandler); // get current new handler if(curhandler == 0) (*curhandler)(); else throw std::bad_alloc(); }【注】1. 參考重載 operator new.· static void* Carrot::operator new[](size_t size, ...)- static void Carrot::operator delete(void * memory, size_t size) { if(memorty == NULL) return; ...} 【注】1. 參考重載 operator new.· static void Carrot::operator delete[](void * momery, size_t size)▲注:1.本文中成員函數僅指非靜態(tài)成員函數;非成員函數包括自由函數,靜態(tài)成員函數,友元函數?!?.這種調用方法使用了 operator new 的一種重載形式: void * operator new(size_t, void * buff) . 這種重載方式直接返回了傳入的內存地址, 所以這種調用方式中 operator new 其實(shí)什么也沒(méi)做, 于是這個(gè) new operator 調用只使用了其中調用構造函數的部分, 相當于是在調用 placement new. 該重載在 VC7.1 中定義如下:#define __PLACEMENT_NEW_INLINEinline void *__cdecl operator new(size_t, void *_Where) _THROW0(){ // construct array with placement at _Wherereturn (_Where);}←3.和 placement new 一樣, nothrow new 也是 operator new 的一種重載形式, nothrow 是 中聲明的一個(gè)對象. 該重載在 VC7.1 中的聲明為:...struct nothrow_t { // placement new tag type to suppress exceptions };extern const nothrow_t nothrow; // constant for placement new tag...void *__cdecl operator new(size_t, const std::nothrow_t&) _THROW0();←4.在 VC7.1 中, 不將 operator new 聲明為靜態(tài)函數仍然可以通過(guò)編譯, 但是如果在函數里面使用了非靜態(tài)成員則會(huì )產(chǎn)生編譯錯誤. 可見(jiàn), 即使不將 operator new 聲明為靜態(tài)函數編譯器也會(huì )將其作為靜態(tài)函數來(lái)處理的. 使用是即使編譯器默認把 operator new 當作靜態(tài)函數也應該顯式的將其聲明為 static 函數. ←5. 即對 && 操作符如果左操作數為 false, 則直接返回 false 而不會(huì )去檢測右操作數; 對 || 操作符如果左操作數為 true, 則直接返回 true 而不會(huì )檢測右操作數的值. 于是類(lèi)似這樣的代碼可以是安全的: if( (p != NULL) && strlen(p) < 10 )... 如果 p == NULL, strlen 就不會(huì )被調用. 但是重載的 operator&& 和 operator|| 是作為一個(gè)函數, 要在所有的參數求值完成后才會(huì )調用此操作符.←