重載 operator() 的類的對象以及函數指針叫函數對象。
類重載 operator() 有一些好處:
- operator() 可以是重載的函數。傳遞這個函數對象給泛型庫時,可以把重載集作為一個整體傳過去。而傳函數指針的話只能傳單體。
- 函數對象可以有狀態,這可以實現閉包。 C++ 語核里有 lambda 表達式,它可以創建自動捕獲外圍變量(或者攜帶自定義狀態)的函數對象。
目前類重載的 operator() 有一些缺點:
- 它不能是 static 成員函數。這使得標准庫中大量存在的無狀態函數對象,以及可能廣泛使用的自定義無狀態函數對象,可能會帶來額外開銷。也使得無捕獲的 lambda 實現變得復雜。(至少需要有一個非 static 的 operator() 和 static 的額外成員函數。 Lambda 表達式需要能被隱式轉換成指向后者的指針。)
用法為:
class ShorterThan { public: explicit ShorterThan(int maxLength) : length(maxLength) {} bool operator() (const string& str) const { return str.length() < length; } private: const int length; };
- count_if(myVector.begin(), myVector.end(), ShorterThan(length)); //直接調用即可
這里需要注意的是,不要糾結於語法問題:ShorterThan(length)似乎並沒有調用operator()函數?其實它調用了,創建了一個臨時對象。你也可以自己加一些輸出語句看一看。
類型轉換
C++中可以定義類型轉換函數,將類對象轉換為其他類型,函數原型為:operator Type()
- 類型轉換函數與轉換構造函數具有同等的地位;
- 類型轉換函數使得編譯器有能力將對象轉化為其他類型;
- 編譯器能夠隱式的使用類型轉換函數
#include <iostream> #include <string> class Test; class Value { public: Value() { } Value(Test& t) // false // explicit Value(Test& t) // Ok { std::cout << "explicit Value(Test& t)" << std::endl; } }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } operator Value() { Value ret; std::cout << "operator Value()" << std::endl; return ret; } }; int main() { Test t(100); Value v = t; return 0; }
從輸出結果我們可以發現:轉換構造函數和類型轉換函數發生沖突了,編譯器不知道應該調用哪個函數。因此發生了錯誤。
當然我們可以使用explicit關鍵字抑制隱式的轉換構造函數,讓程序只調用類型轉換函數。但是,我們無法抑制隱式的類型轉換函數。