- 仿函數 也叫函數對象
- 1,具有函數性質的對象;2,這種東西在調用者可以像函數一樣地被調用(調用),在被調用者則以對象所定義的function call operator扮 演函數的實質角色。
- 要將某種 “操作”當做算法的參數,唯一辦法就是先將該"操作” (可能擁有數條以上的指令)設計為一個函數,再將函數指針當做算法的一個參數;或是將該“操作”設計為一個所謂的仿函數(就語言層面而言是個class), 再以該 仿函數產生一個對象,并以此對象作為算法的一個參數.
- 根據以上陳述,既然函數指針可以達到“將整組操作當做算法的參數”,那又何必有所謂的仿函數呢?原因在于函數指針畢竟不能滿足STL對抽象性的要求,也不能滿足軟件積木的要求—— 函數指針無法和STL其它組件(如配接器adapter, 第8 章)搭配,產生更靈活的變化。
- 就實現觀點而言,仿函數其實上就是一個“行為類似函數”的對象。為了能夠“行為類似函數”,其類別定義中必須自定義(或說改寫、重載)function call運算 子 (operator()? 語法和語意請參考1.9.6節).擁有這樣的運算子后,我們就 可以在仿函數的對象后面加上一對小括號,以此調用仿函數所定義的 operator()
- ?其中第一種用法比較為大家所熟悉,greater<int> i g 的意思是產生一個名為 i g 的對象,ig(4,6)則是調用其operator (),并給予兩個參數4,6。第二種用法中的greater<int> ()意思是產生一個臨時(無名的)對象,之后的(4,6)才 是指定兩個參數4,6。臨時對象的產生方式與生命周期,請參見192節。
- ?S T L 仿函數的分類,若以操作數(operand)的個數劃分,可分為一元和二元 仿函數,若以功能劃分,可分為算術運算(Arithmetic)、關系運算(Rational)、 邏輯運算(Logical)三大類。任何應用程序欲使用S T L 內建的仿函數,都必須含入 <functional>頭文件, S G I 則將它們實際定義于<stl_function.h > 文件中。以下分別描述。
7.2 可 配 接 (Adaptable ) 的關鍵
- 在 S T L 六大組件中,仿函數可說是體積最小、觀念最簡單、實現最容易的一個但是小兵也能立大功—— 它扮演一種"策略”2角色,可以讓S T L 算法有更靈活的演出。而更加靈活的關鍵,在于S T L 仿函數的可配接性(adaptability)。
- 是的, S T L 仿函數應該有能力被函數配接器(function adapter,第 8 章)修飾,彼此像積木一樣地串接? 為了擁有配接能力,每一個仿函數必須定義自己的相應型別(associative types), 就像迭代器如果要融入整個S T L 大家庭,也必須依照 規定定義自己的5 個相應型別一樣。這些相應型別是為了讓配接器能夠取出,獲得仿函數的某些信息。相應型別都只是一些 typedef, 所有必要操作在編譯期就全部 完成了,對程序的執行效率沒有任何影響,不帶來任何額外負擔0
7.2.1 unary_function
- unary_function用來呈現一元函數的參數型別和回返值型別。其定義非常簡單:
?7.2.2 bin ary—function
- binary_function用來呈現二元函數的第一參數型別、第二參數型別,以及 回返值型別。其定義非常簡單:
?7.3 算術類 (Arithmetic ) 仿函數
- STL內建的“算術類仿函數”,支持加法、減法、乘法、除法、模數(余數,modulus)和否定(negation)運算。除了 “否定”運算為一元運算,其它都是二 元運算。
?
- ?一般而言不會有人在這么單純的情況下運用這些功能極其簡單的仿函數。仿函
數的主要用途是為了搭配STL算法。例如以下式子表示要以遞增次序對vector iv進行排序:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <functional>int main(int argc,char* argv[]){std::equal_to<int>equal_to_obj{};std::not_equal_to<int>not_equal_to_obj{};std::greater<int>greater_obj{};std::greater_equal<int>greater_equal_obj{};std::less<int>less_obj{};std::less_equal<int>less_equal_obj{};//調用 創建的對象 旅行函數的功能std::cout << equal_to_obj(3,5) << std::endl; //0std::cout << not_equal_to_obj(3,5) << std::endl; //1std::cout << greater_obj(3,5) << std::endl; //0std::cout << greater_equal_obj(3,5) << std::endl; //0std::cout << less_obj(3,5) << std::endl; //1std::cout << less_equal_obj(3,5) << std::endl; //1// 以下直接以仿函數的臨時對象履行函數功能// 語法分析:functor<T>()是一個臨時對象,后面再接一對小括號// 意指調用 function call operatorstd::cout << std::equal_to<int>()(3,5) << std::endl;std::cout << std::not_equal_to<int>()(3,5) << std::endl;std::cout << std::greater_equal<int>()(3,5) << std::endl;std::cout << std::greater_equal<int>()(3,5) << std::endl;std::cout << std::less<int>()(3,5) << std::endl;std::cout << std::less_equal<int>()(3,5) << std::endl;return 0;
}
?7.5 邏 輯 運 算 類 (Logical)仿函數
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <functional>int main(int argc,char* argv[]){std::logical_and<int>and_obj{};std::logical_or<int>or_obj{};std::logical_not<int>not_obj{};// 以下運用上述對象,履行函數功能std::cout << and_obj(true, true) << std::endl;std::cout << or_obj(true, false)<< std::endl;std::cout << not_obj(true) << std::endl;// 以下直接以仿函數的臨時對象履行函數功能// 語法分析: functor<T>() 是一個臨時對象,后面再接一對小括號// 意指調用 function call operatorstd::cout << << std::endl;std::cout << << std::endl;std::cout << << std::endl;return 0;
}
?7 .6 證同 ( id en tity ) 、 選 擇 (se le c t) 、 投 射 (project)
?