()
運算子過載為成員函數,這個類就稱為函數物件類,這個類的物件就是函數物件。函數物件是一個物件,但是使用的形式看起來像函數呼叫,實際上也執行了函數呼叫,因而得名。#include <iostream> using namespace std; class CAverage { public: double operator()(int a1, int a2, int a3) { //過載()運算子 return (double)(a1 + a2 + a3) / 3; } }; int main() { CAverage average; //能夠求三個整數平均數的函數物件 cout << average(3, 2, 3); //等價於 cout << average.operator(3, 2, 3); return 0; }程式的輸出結果是:
()
是目數不限的運算子,因此過載為成員函數時,有多少個引數都可以。
template <class InIt, class T, class Pred>
T accumulate(InIt first, InIt last, T val, Pred op);
template <class InIt, class T, class Pred> T accumulate(InIt first, Init last, T init, Pred op) { for (; first != last; ++first) init = op(init, *first); return init; };此模板被範例化後,
op(init, *first)
必須要有定義,則 op 只能是函數指標或者函數物件。因此呼叫該 accmulate 模板時,形參 op 對應的實參只能是函數名、函數指標或者函數物件。#include <iostream> #include <vector> #include <numeric> //accumulate 在此標頭檔案定義 using namespace std; template <class T> void PrintInterval(T first, T last) { //輸出區間[first,last)中的元素 for (; first != last; ++first) cout << *first << " "; cout << endl; } int SumSquares(int total, int value) { return total + value * value; } template<class T> class SumPowers { private: int power; public: SumPowers(int p) :power(p) { } const T operator() (const T & total, const T & value) { //計算 value的power次方,加到total上 T v = value; for (int i = 0; i < power - 1; ++i) v = v * value; return total + v; } }; int main() { const int SIZE = 10; int a1[] = { 1,2,3,4,5,6,7,8,9,10 }; vector<int> v(a1, a1 + SIZE); cout << "1) "; PrintInterval(v.begin(), v.end()); int result = accumulate(v.begin(), v.end(), 0, SumSquares); cout << "2) 平方和:" << result << endl; result = accumulate(v.begin(), v.end(), 0, SumPowers<int>(3)); cout << "3) 立方和:" << result << endl; result = accumulate(v.begin(), v.end(), 0, SumPowers<int>(4)); cout << "4) 4次方和:" << result; return 0; }程式的輸出結果如下:
int accumulate(vector <int>::iterator first, vector <int>::iterator last, int init, int(*op)(int, int)) { for (; first != last; ++first) init = op(init, *first); return init; }形參 op 是一個函數指標,而
op(init, *first)
就呼叫了指標 op 指向的函數,在第 37 行的情況下就是函數 SumSquares。int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, SumPowers<int> op) { for (; first != last; ++first) init = op(init, *first); return init; }形參 op 是一個函數物件,而
op(init, *first)
等價於:
op.operator()(init, *first);
即呼叫了 SumPowers<int> 類的 operator() 成員函數。
template <class_Randlt>
void sort(_Randlt first, _RandIt last);
<
進行的。如果表示式a<b
的值為 true,則 a 排在 b 前面;如果a<b
的值為 false,則 b 未必排在 a 前面,還要看b<a
是否成立,成立的話 b 才排在 a 前面。要使用這個版本的 sort 演算法,待排序的物件必須能用<
運算子進行比較。
template <class_Randlt, class Pred>
void sort(_Randlt first, _RandIt last, Pred op);
op(a, b)
進行的。如果該表示式的值為 true,則 a 比 b 小;如果該表示式的值為 false,也不能認為 b 比 a 小,還要看op(b, a)
的值。總之,op 定義了元素比較大小的規則。下面是一個使用 sort 演算法的例子。
#include <iostream> #include <algorithm> //sort演算法在此標頭檔案中定義 using namespace std; template <class T> void Printlnterva1(T first, T last) { //用以輸出 [first, last) 區間中的元素 for (; first != last; ++first) cout << *first << " "; cout << endl; } class A { public: int v; A(int n) : v(n) {} }; bool operator < (const A & a1, const A & a2) { //過載為 A 的 const 成員函數也可以,過載為非 const 成員函數在某些編譯器上會出錯 return a1.v < a2.v; } bool GreaterA(const A & a1, const A & a2) { //v值大的元素作為較小的數 return a1.v > a2.v; } struct LessA { bool operator() (const A & a1, const A & a2) { //v的個位數小的元素就作為較小的數 return (a1.v % 10) < (a2.v % 10); } }; ostream & operator << (ostream & o, const A & a) { o << a.v; return o; } int main() { int a1[4] = { 5, 2, 4, 1 }; A a2[5] = { 13, 12, 9, 8, 16 }; sort(a1, a1 + 4); cout << "1)"; Printlnterva1(a1, a1 + 4); //輸出 1)1 2 4 5 sort(a2, a2 + 5); //按v的值從小到大排序 cout << "2)"; Printlnterva1(a2, a2 + 5); //輸出 2)8 9 12 13 16 sort(a2, a2 + 5, GreaterA); //按v的值從大到小排序 cout << "3)"; Printlnterva1(a2, a2 + 5); //輸出 3)16 13 12 9 8 sort(a2, a2 + 5, LessA()); //按v的個位數從小到大排序 cout << "4)"; Printlnterva1(a2, a2 + 5); //輸出 4)12 13 16 8 9 return 0; }編譯至第 45 行時,編譯器將 sort 範例化得到的函數原型如下:
void sort(A* first, A* last, bool (*op)(const A &, const A &) );
該函數在執行過程中,當要比較兩個元素 a、b 的大小時,就是看 op(a, b) 和 op(b, a) 的返回值。本程式中 op 指向 GreaterA,因此就用 GreaterA 定義的規則來比較大小。void sort( A* first, A* last, LessA op);
該函數在執行過程中,當要比較兩個元素 a、b 的大小時,就是看 op(a, b) 和 op(b, a) 的返回值。本程式中,op(a, b) 等價於 op.opeartor(a, b),因此就用 LessA 定義的規則來比較大小。template <class T> struct greater { bool operator()(const T& x, const T& y) const{ return x > y; } };假設有以下陣列:
int a[4] = {3, 5, 34, 8};
要將該陣列從大到小排序,則只需寫:sort( a, a+4, greater<int>() );
要使用 greater 模板,須確保>
運算子本來就有定義,或經過了適當的過載。<
運算子;另一個是函數模板,原型如下:
template <class Pred>
void sort(Pred op);
list<int> lst;
如果希望將 lst 中的元素按其整數數值從大到小排序,只需寫:lst.sort( greater<int>() );
在使用關聯容器和許多演算法時,都可以用函數物件來定義比較大小的規則,以及其他一些規則和操作。函數物件類別範本 | 成員函數 T operator ( const T & x, const T & y) 的功能 |
---|---|
plus <T> | return x + y; |
minus < > | return x - y; |
multiplies <T> | return x * y; |
divides <T> | return x / y; |
modulus <T> | return x % y; |
成員函數 bool operator( const T & x, const T & y) 的功能 | |
equal_to <T> | return x == y; |
not_equal_to <T> | return x! = y; |
greater <T> | return x > y; |
less <T> | return x < y; |
greater_equal <T> | return x > = y; |
less_equal <T> | return x <= y; |
logical_and <T> | return x && y; |
logical_or <T> | return x || y; |
成員函數 T operator( const T & x) 的功能 | |
negate <T> | return - x; |
成員函數 bool operator( const T & x) 的功能 | |
logical_not <T> | return ! x; |
multiplies<double> () (x, y)
template <class_Tp> struct less { bool operator() (const_Tp & __x, const_Tp & __y) const { return __x < __y; } };要判斷兩個 int 變數 x、y 中 x 是否比 y 小,可以寫:
if( less<int>()(x, y) ) { ... }
<
運算子進行的。通過 10.3.4 節可知,sort 和 list::sort 都可以通過一個函數物件或函數自定義比較元素大小的規則。例如以下的 sort 版本:
template <class_RandIt, class Pred>
void sort(_RandIt first, _RandIt last, Pred op);
<
運算子,以規定元素之間的大小關係。STL 中還有許多演算法都可以自定義比較器。在自定義比較器 op 的情況下,以下三種說法是等價的:
x和y相等
與op(x, y)和op(y, x)都為假
是等價的。