生活随笔
收集整理的這篇文章主要介紹了
boost::function的用法(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
boost function是一組類和模板組合,用于包裝各種函數。從功能上,它類似于函數指針,但是比函數指針的功能更強大。
使用boost function,必須包含頭文件
[cpp]?view plaincopy
#include?<boost/function.hpp>??
除了頭文件外,不需要額外的庫。
注意,boost function有兩種形式:一種為推薦形式;另外一種為可移植形式。推薦形式的語法更加簡潔;可移植形式的可移植性好,但是語法羅嗦。由于目前的gcc/vc的版本都已經能夠使用推薦形式了,因此,可移植形式就不在描述。有興趣的可以參閱boost相關文檔。
boost function 基本用法
例如,有一個函數
[cpp]?view plaincopy
float?int_div(int?x,?int?y)?? {?? ????return?((float)x)/y;?? }??
我們可以這樣使用
[cpp]?view plaincopy
boost::function<float?(int?x,?int?y)>?f;?? f?=?int_div;?? std::cout<<?f(5,3)?<<?std::endl;??
可以看到,它的用法和函數指針很相似的。
當然,boost::function不止這些,請看下面的函數對象:
[cpp]?view plaincopy
struct?int_add?{?? ????float?operator()(int?x,?int?y)?{?? ????????return?(float)(x?+?y);?? ????}?? };??
上面的 boost::function<float (int x, int y)> f 聲明的f對象,仍舊可以保存int_add:
[cpp]?view plaincopy
f?=?int_add();?? std::cout?<<?"f?add?:?"<<?f(10,20)?<<?std::endl;??
另外,boost::function還可以用來判斷函數是否為空
[cpp]?view plaincopy
if(f)?? ????std::cout??<<?"?f?is?ok!"<<?std::endl;??
要清空f,可以使用
[cpp]?view plaincopy
f?=?0;?? if(!f)?? ????std::cout?<<?"f?is?cleard!"?<<?std::endl;??
針對成員函數
成員函數,也可以被綁定,如有類
[cpp]?view plaincopy
struct?X?{?? ????int?foo(int?x)?{?? ????????std::cout?<<?"X?"?<<?this?<<?"?foo?x="<<x?<<?std::endl;?? ????????return?x?+?100;?? ????};?? };?? 可以這樣使用
[cpp]?view plaincopy
boost::function<int?(X*,?int)>?mf;?? mf?=?&X::foo;?? ?? X?x;?? mf(&x,?5);??
和bind同時使用
在需要包裝參數的場合,我們可以配合boost::bind一起使用。
首先,加入boost::bind的頭文件
[cpp]?view plaincopy
#include?<boost/bind.hpp>?? 這樣使用
[cpp]?view plaincopy
boost::function<int?(int)>?mbf;?? mbf?=?bind(&X::foo,?&x,?_1);?? mbf(10);?? bind將x的指針保存在function對象中。
function factory
function factory是一個封裝類工廠的模板。它有兩種,一種是value_factory,一種是factory。
[cpp]?view plaincopy
boost::factory<T*>()(arg1,arg2,arg3)??? ?? ?? boost::value_factory<T>()(arg1,arg2,arg3)?? ?? 使用function factory的原因
我們考慮這樣的場景:使用
抽象工廠模式,有一個接口,有若干個實現,通常的做法是這樣的:
[cpp]?view plaincopy
?? class?Interface??? {?? public:?? ???virtual?void?print(int?a)?=?0;??? };?? ?? class?Interface_Factory?{?? public:?? ????virtual?Interface?*?create()?=?0;?? };?? 然后,我們有若干個實現
[cpp]?view plaincopy
class?ImplA?:?public?Interface?? {?? public:?? ???virtual?void?print(int?a)?{?? ??????std::cout?<<?"==?A?==??a="?<<?a?<<?std::endl;?? ???}?? };?? ?? class?ImplA_Factory?:?public?Interface_Factory?? {?? public:?? ????Interface?*?create()?{?return?new?ImplA();?}?? ????static?ImplA_Factory?_implAFactory;?? };?? ImplA_Factory?ImplA_Factory::_implAFactory;?? ?? ?? ?? class?ImplB?:?public?Interface?? {?? public:?? ???virtual?void?print(int?a)?{?? ??????std::cout?<<?"==?B?==??a="?<<?a?<<?std::endl;?? ???}?? };?? ?? class?ImplB_Factory?:?public?Interface_Factory?? {?? public:?? ????Interface?*?create()?{?return?new?ImplB();?}?? ????static?ImplB_Factory?_implBFactory;?? };?? ImplB_Factory?ImplB_Factory::_implBFactory;?? 如果你要使用它,就需要這些寫
[cpp]?view plaincopy
std::map<std::string,?Interface_Factory*>?factories;?? ?? int?main()?? {?? ????factories["A"]?=?&ImplA_Factory::_implAFactory;?? ????factories["B"]?=?&ImplB_Factory::_implBFactory;?? .....?? }?? 如果仔細觀察下,就會發現,實際上,ImplA_Factory和ImplB_Factory的內容幾乎都一樣。但是卻寫了不少重復性的代碼。factory就是解決該問題的。
factory的解決之道
使用boost::factory,是完全不需要定義Interface_Factory接口和對應的實現的,我們定義一個boost::function對象,替代Interface_Factory
[cpp]?view plaincopy
typedef?boost::function<?I?*()?>?I_factory;??? 用boost::factory替代ImplA_Factory和ImplB_Factory:
[cpp]?view plaincopy
std::map<std::string,?I_factory>?factories;?? ....?? ?? ????factories["A"]?=?boost::factory<ImplA*>?();???? ????factories["B"]?=?boost::factory<ImplB*>?();??? 在使用的時候,與普通方法絲毫不差,如
[cpp]?view plaincopy
void?run_interface(const?char*?name)?? {?? ????I_factory?factory?=?factories[name];?? ????if(!factory)?? ????{????? ????????std::cout<<"factory?"?<<?name?<<?"?is?not?exist"?<<?std::endl;?? ????????return;?? ????}????? ????I?*i?=?factory();?? ????i->print(100);?? ????delete?i;?? }?? 通過判斷factory的函數是否為空,就可以知道對應的類實現是否存在。我們可以這樣簡單的使用
[cpp]?view plaincopy
run_interface("A");?? run_interface("B");?? run_interface("C");?? 由于"C"對象不存在,因此,將打印 "factory C is not exist"的信息。
OverloadedFunction
考慮下面的代碼
[cpp]?view plaincopy
const?std::string&?identity_s(const?std::string&?x)??? ????{?return?x;?}?? ?? int?identity_i_impl(int?x)?{?return?x;?}?? int?(&identity_i)(int)?=?identity_i_impl;??? ?? double?identity_d_impl(double?x)?{?return?x;?}?? boost::function<double?(double)>?identity_d?=?identity_d_impl;??? 在調用他們的時候,必須使用各自的函數名:identity_i, indentity_s, indentity_d; 例如
[cpp]?view plaincopy
BOOST_TEST(identity_s("abc")?==?"abc");?? BOOST_TEST(identity_i(123)?==?123);?? BOOST_TEST(identity_d(1.23)?==?1.23);?? 但是,使用OverlaodedFunction,就可以使用統一的名字identity來調用了:
[cpp]?view plaincopy
boost::overloaded_function<?? ??????const?std::string&?(const?std::string&)?? ????,?int?(int)?? ????,?double?(double)?? >?identity(identity_s,?identity_i,?identity_d);?? ?? ?? BOOST_TEST(identity("abc")?==?"abc");?? BOOST_TEST(identity(123)?==?123);?? BOOST_TEST(identity(1.23)?==?1.23);??
總結
以上是生活随笔為你收集整理的boost::function的用法(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。