函數(shù)對(duì)象與高級(jí)編程
千萬(wàn)不要忘記,在C++中,最好不要只從語(yǔ)言本身來(lái)判定,它被設(shè)計(jì)為可以通過(guò)庫(kù)來(lái)彌補(bǔ)本身的缺點(diǎn)
Bind成功的一個(gè)關(guān)鍵是采用統(tǒng)一的語(yǔ)法來(lái)創(chuàng)建函數(shù)對(duì)象,以及對(duì)應(yīng)于使用該庫(kù)的類型只有很少的要求。這種設(shè)計(jì)使得無(wú)需關(guān)注如何去寫與你的類型一起工作的代碼,而只需關(guān)注我們最關(guān)心的一點(diǎn),代碼如何工作以及它實(shí)際上做了什么。
弄明白如何使用bind的關(guān)鍵是,占位符的概念。占位符用于表示提供給結(jié)果函數(shù)對(duì)象的參數(shù),Boost.Bind支持最多九個(gè)參數(shù)。占位符被命名為_(kāi)1,_2,直至_9,你要把它們放在你原先放參數(shù)的地方。
普通函數(shù)與成員函數(shù)之間有著非常大的差異,在綁定一個(gè)成員函數(shù)時(shí),bind表達(dá)式的第一個(gè)參數(shù)必須是成員函數(shù)所在類的實(shí)例!理解這個(gè)規(guī)則的最容易的方法是,這個(gè)顯式的參數(shù)將取代隱式的this,被傳遞給所有的非靜態(tài)成員函數(shù)。
bind總是執(zhí)行復(fù)制。如果你通過(guò)值來(lái)傳遞,對(duì)象將被復(fù)制,這可能對(duì)性能有害或者產(chǎn)生不必要的影響。為了避免復(fù)制對(duì)象,你可以使用boost::ref/boost::cref或者使用指針語(yǔ)義。
正如我們所看到的,沒(méi)有一個(gè)明顯的方法來(lái)保存我們的綁定器以備后用,我們只知道它們是帶有某些(未知)的特征的兼容函數(shù)對(duì)象。但是,如果使用 Boost.Function, 保存函數(shù)用于以后的調(diào)用正是那個(gè)庫(kù)要做的,并且它兼容于 Boost.Bind, 可以把綁定器賦值給函數(shù),保存它們并用于以后的調(diào)用。這是一個(gè)非常有用的概念,它可以用于適配并提高了松耦合。
Lambda 庫(kù)
Boost.Lambda可以創(chuàng)建直接定義和調(diào)用的函數(shù)對(duì)象,或者把它保存起來(lái)晚一些再調(diào)用。這與Boost.Bind庫(kù)所提供的很相似,但Boost.Lambda除了可以進(jìn)行參數(shù)綁定,還有其他功能,增加了控制結(jié)構(gòu)、表達(dá)式到函數(shù)對(duì)象的自動(dòng)轉(zhuǎn)換,還支持在Lambda表達(dá)式中的異常處理。
Lambda庫(kù)用于解決一個(gè)使用標(biāo)準(zhǔn)庫(kù)算法時(shí)常會(huì)遇見(jiàn)的問(wèn)題,即需要為了滿足算法的要求而定義很多簡(jiǎn)單的函數(shù)對(duì)象。
Function 庫(kù)
保存函數(shù)指針和函數(shù)對(duì)象,用于后續(xù)的調(diào)用
boost::function 的缺省行為是復(fù)制它要調(diào)用的函數(shù)對(duì)象,這一點(diǎn)很重要。如果這導(dǎo)致不正確的語(yǔ)義,或者如果某些函數(shù)對(duì)象的復(fù)制代價(jià)太高,你就必須把函數(shù)對(duì)象包裝在 boost::reference_wrapper 中,那樣 boost::function 的復(fù)制就會(huì)是一個(gè) boost::reference_wrapper 的拷貝,它恰好持有一個(gè)到原始函數(shù)對(duì)象的引用。你無(wú)須直接使用 boost::reference_wrapper ,你可以使用另兩個(gè)助手函數(shù),ref 和 cref。 這兩函數(shù)返回一個(gè)持有到某特定類型的引用或 const 引用的 reference_wrapper。
代價(jià)的考慮:與使用函數(shù)指針相比,使用 Boost.Function 也有一些缺點(diǎn),特別是對(duì)象大小的增加。顯然,一個(gè)函數(shù)指針只占用一個(gè)函數(shù)指針的空間大小(這當(dāng)然了!),而一個(gè) boost::function實(shí)例占的空間有三倍大。函數(shù)指針在調(diào)用時(shí)的效率也稍高一些,因?yàn)楹瘮?shù)指針是被直接調(diào)用的,而 Boost.Function 可能需要使用兩次函數(shù)指針的調(diào)用。最后,可能在某些需要與C庫(kù)保持后向兼容的情形下,只能使用函數(shù)指針。
與使用函數(shù)指針相比,使用 Boost.Function 有幾個(gè)優(yōu)點(diǎn):通過(guò)兼容的函數(shù)對(duì)象而不是真實(shí)的簽名放松了對(duì)簽名的要求;可以使用綁定器,如 Boost.Bind 和 Boost.Lambda;可以在調(diào)用函數(shù)之前檢測(cè)函數(shù)是否為空,即是否存在目標(biāo)函數(shù);可以使用帶狀態(tài)的對(duì)象而不僅限于無(wú)狀態(tài)函數(shù)。這些優(yōu)點(diǎn)表明了使用 Boost.Function 替代C風(fēng)格的回調(diào)可以解決這類普遍存在的問(wèn)題。使用 Boost.Function 比使用函數(shù)指針要多付出一點(diǎn)點(diǎn)代價(jià),只有這一點(diǎn)小代價(jià)是被禁止時(shí),才應(yīng)該考慮使用函數(shù)指針技術(shù)。
Signals庫(kù)
函數(shù)和函數(shù)對(duì)象的靈活多點(diǎn)回調(diào)
健壯的觸發(fā)器及事件處理的機(jī)制
兼容于函數(shù)對(duì)象工廠,如Boost.Bind和Boost.Lambda
Boost.Signals庫(kù)具體化了信號(hào)(signals)和插槽(slots),信號(hào)指的是某種可被“拋出”的東西,而插槽是接收該信號(hào)的連接者。