中國大學MOOC程序設計與算法(三):C++ 面向對象程序設計 第八週 標準模板庫STL(一) 筆記 之 函數對象

第八週 標準模板庫STL(一)
1.string類
2.標準模板庫STL概述(一)
3.標準模板庫STL概述(二)
4.vector,deque和list
5.函數對象

5.函數對象

函數對象

如果一個類重載了運算符“()”,則該類的對象就都是函數對象。函數對象也是對象,但是用起來看上去和函數非常像,實際上是執行了成員函數的調用。

class CMyAverage {
	public:
		double operator()( int a1, int a2, int a3 ) {//重載 () 運算符
		return (double)(a1 + a2+a3) / 3;
		}
};
CMyAverage average; //函數對象
cout << average(3,2,3); // average.operator()(3,2,3), 用起來看上去象函數調用 輸出 2.66667

函數對象的應用

STL裏有以下對一個區間操作的模板:

template<class InIt, class T, class Pred>
T accumulate(InIt first, InIt last, T val, Pred pr);

pr 就是個函數對象,pr也可以是個函數。
對[first,last)中的每個迭代器 I,執行 val = pr(val,* I) ,返回最終的val。

Dev C++ 中accumulate的源代碼1:

template<typename _InputIterator, typename _Tp>// typename 等效於class
_Tp accumulate(_InputIterator __first, _InputIterator __last,_Tp __init)
{
	for ( ; __first != __last; ++__first)
		__init = __init + *__first;
	return __init;
}

Dev C++ 中的 accumulate 源代碼2:

template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
{
	for ( ; __first != __last; ++__first)
		__init = __binary_op(__init, *__first);
	return __init;
}
//調用accumulate 時,和 __binary_op對應的實參可以是個函數名稱、函數指針或函數對象。

函數例子:

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
using namespace std;
int sumSquares( int total, int value){ 
	return total + value * value;
}
template <class T>
void PrintInterval(T first, T last){ //輸出區間[first,last)中的元素
	for( ; first != last; ++ first)
		cout << * first << " ";
	cout << endl;
}
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;
}
輸出:
1) 1 2 3 4 5 6 7 8 9 10
2)  平方和: 385
3)  立方和: 3025
4) 4 次方和: 25333

原理
int result = accumulate(v.begin(),v.end(),0,SumSquares);
實例化出:
int ( * op)( int,int)表明定義了一個返回值爲int,輸入類型是兩個int的函數指針

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;
}

int result = accumulate(v.begin(),v.end(),0,SumPowers(3));
實例化出:
SumPowers op表明op是一個函數對象

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;
}

STL 中的函數對象類模板:

equal_to
greater
less …….
這些模板可以用來生成函數對象。
頭文件:functional

greater 函數對象類模板

template<class T>
struct greater : public binary_function<T, T, bool> {
	bool operator()(const T& x, const T& y) const {
		return x > y;
	}
};

這個greater的大小和數學上的大小正好是反過來的,降序。這點我不太懂。

binary_function定義:

template<class Arg1, class Arg2, class Result>
struct binary_function {
	typedef Arg1 first_argument_type;
	typedef Arg2 second_argument_type;
	typedef Result result_type; 
};

greater 的應用
list 有兩個sort函數
void sort();前面例子中看到的是不帶參數的sort函數,它將list中的元素按 < 規定的比較方法升序排列。
list還有另一個sort函數:

template <class Compare>
void sort(Compare op);

將list中的元素按op規定的比較方法升序排列。即要比較x,y的大小時,看op(x,y)的返回值,爲true則認爲x小於y,和簡單的小於號還是有區別的。

#include <list>
#include <iostream>
#include <iterator>
using namespace std;
class MyLess {
	public:
		bool operator()( const int & c1, const int & c2 ){
			return (c1 % 10) < (c2 % 10);//誰的個位數小,誰就小
		}
};
template <class T>
void Print(T first, T last){
	for(;first != last;++first)
		cout << *first << ",";
}
int main()
{ 
	const int SIZE = 5;
	int a[SIZE] = {5,21,14,2,3};
	list<int> lst(a, a+SIZE);
	lst.sort(MyLess());
	Print(lst,begin(),  lst.end());
	cout << endl;
	lst.sort(greater<int>()); //greater<int>()是個對象,本句進行降序排序
	Print(lst,begin(),  lst.end());
	return 0;
} 
輸出:
21,2,3,14,5,
21,14,5,3,2,

引入函數對象後,在STL中使用自定義的“大”,“小”關係

關聯容器和STL中許多算法,都是可以用函數或函數對象自定義比較器的。在自定義了比較器op的情況下,以下三種說法是等價的:

  1. x小於y
  2. op(x,y)返回值爲true
  3. y大於x

例子:寫出MyMax模板

#include <iostream>
#include <iterator>
using namespace std;
class MyLess{
	public:
		bool operator() (int a1,int a2){//誰的個位數小誰就小
			if( ( a1 % 10 ) < (a2%10) )
				return true;
			else
				return false;
		}
};
bool MyCompare(int a1,int a2){//誰的個位數大誰就小
	if( ( a1 % 10 ) < (a2%10) )
		return false;
	else
		return true;
}
int main()
{
	int a[] = {35,7,13,19,12};
	cout << MyMax(a,5,MyLess()) << endl;
	cout << MyMax(a,5,MyCompare) << endl;
	return 0;
}

要輸出:
19
12
則MyMax定義如下:

template <class T, class Pred>
T MyMax( T * p, int n, Pred myless){
	T tmpmax = p[0];
	for( int i = 1;i < n;i ++ )
		if( myless(tmpmax,p[i]))
			tmpmax = p[i];
	return tmpmax;
};

發佈了53 篇原創文章 · 獲贊 4 · 訪問量 1978
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章