1.說明ios
[1]重載運算符函數的參數個數,應該與參與這個運算符的運算對象數量同樣多,可是若是是成員函數,則參數數量要少一個,由於第一個參數是this。例如:算法
#include <stdio.h> #include <stdlib.h> using namespace std; class ca { public: int value; //重載爲成員函數格式 int operator+(const ca &v){ return this->value + v.value; // 等同於return value+v.value; } }; //重載爲非成員函數格式 int operator+(const ca &v1, const ca &v2) { return v1.value + v2.value; } int main() { ca a, b; a.value = 10; b.value = 20; printf("a+b:%d\n", a + b); // 優先用成員函數 return 0; }
[2]運算符重載函數的參數至少要有一個類的成員(或者類類型)做爲參數,而不能都是內置類型(會致使編譯錯誤)。例如int operator+(int, int)是不行的,由於int是內置類型。內置類型的操做符明顯是不能重載的,好比重載了int型的+運算符,那程序其餘地方的int加法都會使用重載的函數,這明顯是不行的。函數
[3]運算符能夠像普通函數同樣調用。例如上面例子的a+b等同於a.operator+(b);。this
[4]不該該重載的運算符(固然理論是能夠重載的,只是重載以後容易出問題):逗號、&、&&、||。spa
[5]必須做爲成員函數的重載運算符:=、[]、()、->,不然會編譯錯誤。指針
[6]重載運算符函數是成員函數時,其實就是運算符左側的對象調用的這個運算符,因此左側對象必須是運算符所屬類的一個對象(這個是固然的,由於第一個參數是這個類的this指針)。code
2.輸入輸出運算符重載對象
[1]首先「<<」和「>>」表示移位操做,而後IO標準庫(iostream庫)重載了這兩個運算符來處理輸入和輸出,本身重載這兩個運算符的目的就是要輸出自定義的類。blog
[2]若是要與iostream庫兼容輸入輸出操做,則本身重載的時候必須做爲非成員函數,這個是由於若是做爲成員函數,則左側的操做對象應該是這個類的對象,這樣就不能兼容iostream庫的輸入輸出操做。固然非要重載爲成員函數,也是能夠編譯經過的,只不過是不能兼容標準庫iostream的輸入輸出操做而已。例如:string
#include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> using namespace std; class ca { public: int value; //重載<<的目的就是要輸出類ca ca & operator<<(const ca &v){ cout << "value:" << v.value << "\n"; return *this; } }; int main() { ca a, b, c; a.value = 1; b.value = 2; c.value = 3; //重載函數做爲成員函數以後,之後只能這樣調用。 //顯然類ca的對象的輸出已經和正常的輸出不能兼容使用了。 a << a; b << a; c << b << a; //例以下面這些都是不兼容的,不能編譯經過的。 (cout << "ca info :") << a; a << b << "hello.\n"; return 0; }
[3]由於IO運算符一般要訪問類的全部成員,正確的作法是把重載的非成員函數聲明爲類的友元函數。
3.遞增和遞減運算符重載
[1]遞增和遞減通常是改變對象的狀態,因此通常是重載爲成員函數。
[2]重載遞增遞減,必定要和指針的遞增遞減區分開。由於這裏的重載操做的是對象,而不是指針(因爲指針是內置類型,指針的遞增遞減是沒法重載的),因此通常狀況的遞增遞減是操做對象內部的成員變量。
[3]遞增和遞減分爲前置和後置狀況,a = ++b;(前置), a = b++;(後置)。由於符號同樣,因此給後置版本加一個int形參做爲區分,這個形參是0,可是在函數體中是用不到的,只是爲了區分前置後置。例如:
#include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> using namespace std; // 例如這裏的重載遞增就是爲了增長pos的值 class ca { public: int pos; //前置遞增就是增長當前對象的pos的值,而且返回當前對象 ca operator++(){ pos++; return *this; } //後置遞增就是增長當前對象的pos的值,而且返回增長pos以前的該對象 ca operator++(int){ ca ret = *this; ++*this; //這個會調用上面的函數,其實這裏能夠換成pos++; return ret; } }; int main() { ca a, b; a.pos = 1; b = a++; cout << "b1:" << b.pos << endl; // b1:1 b = ++a; cout << "b2:" << b.pos << endl; // b1:3 return 0; }
4.重載函數調用運算符「()」
[1]類重載了括號運算符,則該類的對象就能夠當成函數同樣來使用。另外類裏面能夠定義數據成員,這樣就比普通函數多了一些功能,例如保存一些狀態,統計該對象的調用次數等等。
[2]這種對象經常用做泛型算法的實參,由於有些泛型算法能夠提供自定義的比較函數。例如:
#include <stdio.h> #include <stdlib.h> #include <string> #include <vector> #include <iostream> #include <algorithm> using namespace std; void myprint(const string & s) { printf("my print : %s\n", s.c_str()); return ; } class ca { public: int call_times; ca(){call_times = 0;} void operator()(const string & s){ printf("ca print : %s\n", s.c_str()); call_times++; } }; int main() { vector<string> vs; vs.push_back("abc"); vs.push_back("def"); //普通函數也是能夠代替仿函數的,只是功能不如仿函數強大 for_each(vs.begin(), vs.end(), myprint); ca a; for_each(vs.begin(), vs.end(), a); //這裏要注意,這個是值傳遞,傳的是a的副本 printf("ca print call times: %d\n", a.call_times); //因此這個地方的a.call_times仍是0 a("haha"); a("hehe"); printf("ca print call times: %d\n", a.call_times); //如今a.call_times的值就是2了 return 0; }