#眉標=Boost #副標=「Boost技術與應用」系列文章(6) #大標= Boost.Function #作者=文/圖 侯捷 ==本文相關資訊 =========== • 讀者基礎:擁有C++ templates編程經驗與C++標準程式庫使用經驗 • 本文測試環境:VC6, BCB5, G++3.2, VS2003(VC7) • 本系列文章摘要並整理自編寫中的《Boost運用與源碼剖析》by侯捷 ================ ==<灰>=========== class notify_previous { private: int last_value; public: void operator()(int i) { static bool first_time = true; if (first_time) { last_value = i; cout << "First change. no previous." << endl; first_time = false; return; } cout << "Previous value was " << last_value << endl; last_value = i; } }; ================ ==<灰>=========== notify_previous n; n(30); //輸出:First change. no previous. n(40); //輸出:Previous value was 30 ================ ==<灰>=========== //容器內置pointers to function vector vfp; vfp.push_back(¬ify_new); // 稍後會有notify_new的定義 vfp.push_back(¬ify_change); // 稍後會有notify_change的定義 //容器內置functors vector vfo; vfo.push_back(notify_previous());// 稍早已出現notify_previous的定義 //容器內置pointers to member function vector vmf; ================ ==<灰>=========== return-type entity-name (param1-type, param2-type, …param10-type); ================ ==<灰>=========== #include "boost\function1.hpp" //這個表頭檔只定義出boost::function1 boost::function1 f1; //這種寫法的編譯器移植性較高 ================ ==<灰>=========== #include "boost\function2.hpp" //這個表頭檔只定義出boost::function2 boost::function2 f2; //這種寫法的編譯器移植性較高 ================ ==<灰>=========== #include "boost\function.hpp" boost::function f1; //這種寫法在各編譯器上移植性較低 ================ ==<灰>=========== #include "boost\function.hpp" boost::function f2; //這種寫法在各編譯器上移植性較低 ================ ==<灰>=========== void notify_new(int i) { cout << "New value is " << i << endl; //輸出新值 } ================ ==<灰>=========== void notify_change(int i) { cout << "Value has changed." << endl; //輸出「已改變」訊息 } ================ ==<灰>=========== #include using namespace std; using namespace boost; class notifier { private: typedef function1 FUNCTYPE; //以上也可寫為typedef function FUNCTYPE; vector v; int value; public: template void add_observer(T t) { v.push_back(FUNCTYPE(t)); //任何T 型別都必須能夠轉為 FUNCTYPE } void change_value(int n) { value = n; for (size_t i=0; i< v.size(); ++i) { //notify all v[i](value); } } }; ================ ==<灰>=========== notifier n; n.add_observer(¬ify_new); n.add_observer(¬ify_change); n.add_observer(notify_previous()); n.change_value(428); n.change_value(928); ================ ==<灰>=========== New value is 428 // 這是notify_new()的輸出結果 Value has changed. // 這是notify_change()的輸出結果 First change. no previous. // 這是notify_previous的輸出結果(第一次呼叫) New value is 928 // 這是notify_new()的輸出結果 Value has changed. // 這是notify_change()的輸出結果 Previous value was 428 // 這是notify_previous的輸出結果(第二次呼叫) ================ ==<灰>=========== class X { public: void func1(int i) const { cout << "OK, X func1 done. " << i << endl; } void func2(int i) const { cout << "OK, X func2 done. " << i << endl; } }; ================ ==<灰>=========== //呼叫者(亦即this object)以pass by value傳遞 function2 f1; //或function f1; //呼叫者(亦即this object)以pass by reference傳遞 function2 f2; //或function f2; //呼叫者(亦即this object)以pass by address傳遞 function2 f3; //或function f2; ================ ==<灰>=========== f1= &X::func1; //注意,這裡的&是對函式取址(address-of),與上述的reference無關。 f2= &X::func1; //注意,同上 f3= &X::func1; //注意,同上 ================ ==<灰>=========== X obj; f1(obj, 10); //這樣寫也可以:f1(X(),10); 其中X()是暫時物件 f2(obj, 20); //這樣寫也可以:f2(X(),20); 其中X()是暫時物件 f3(&obj,30); //這樣寫也可以:f3(&X(),30); 其中X()是暫時物件 ================ ==<灰>=========== OK, X func1 done. 10 OK, X func1 done. 20 OK, X func1 done. 30 ================ ==<灰>=========== 如果要將這種「代表著member function」的boost:function放進容器,可以這麼做: //f1,f2,f3沿續前例 function2 f4; f4 = &X::func2; vector< function2 > vmf; //容器 vmf.push_back(f1); //前述各物件中f1,f2,f4相容於容器元素型別.f3不相容 vmf.push_back(f4); vmf.push_back(f2); vmf[0](obj1, 50); //呼叫之 vmf[1](obj1, 60); vmf[2](obj1, 70); ================ ==<灰>=========== OK, X func1 done. 50 OK, X func2 done. 60 OK, X func1 done. 70 ================ ==更多資訊=========== 以下是與本文相關的讀物或網上資源。 • 《STL源碼剖析》by侯捷,第七章 仿函式(Functors)。 • Boost Libraries Documentation, from http://www.boost.org • 《Beyond the C++ Standard Library, An Introduction to Boost》by Bjorn Karlesson, A.W. 2005. ================ ==作者簡介 =========== 侯捷 資訊顧問、專欄主筆、大學執教。常著文章自娛,頗示己志。 侯捷網站:http://www.jjhou.com(繁體) 北京鏡站:http://jjhou.csdn.net(簡體) 永久郵箱:jjhou@jjhou.com ================