C++ 函數對象學習筆記

函數對象本質上是一個類對象,它重載了函數調用運算符 operator()。調用運算符的函數體實現函數的功能。

例如,我們定義類 LessThan

class LessThan {
public:
    bool operator() (const string &s1, const string &s2) {
        return s1.size() < s2.size();
    }
};

LessThan 包含調用運算符的重載,調用運算符的函數體實現了函數的功能:小於操作。
調用運算符的定義第一次看起來有點令人迷惑,因爲出現了兩個小括號。第一個小括號:

operator()

告訴編譯器我們在重載調用運算符。第二個小括號:

(const string &s1, const string &s2)

指定傳遞給調用運算符重載函數的形式參數。

函數對象的定義與普通類對象一樣:

LessThan lt;
string s1("lee");
string s2("leehao");
bool isLess = lt(s1, s2);

其中,語句 bool isLess = lt(s1, s2); 等價於 bool isLess = lt.operator()(s1, s2);

輸出:

1

函數對象一般作爲實參傳遞給泛型算法使用。

我們再定義一個函數對象,它包含一個被重載的調用運算符,判斷是否小於或等於指定的數值,這個指定的數值通過構造函數初始化:

class LessEqualValue {
public:
    LessEqualValue(int val) : _val(val) {}
    bool operator() (int val) {
        return val <= _val;
    }
private:
    int _val;
};

標準庫函數 count_if 可以統計 vector 中符合條件的元素的個數,例如:

std::count_if(vecInt.begin(), vecInt.end(), LessEqualValue(10));

在調用 count_if 時,我們向其第三個參數傳遞了一個臨時函數對象 LessEqualValue(10),以統計 vecInt 向量中小於等於 10 的元素的個數。

完整的測試源代碼:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class LessEqualValue {
public:
    LessEqualValue(int val) : _val(val) {}
    bool operator() (int val) {
        return val <= _val;
    }
private:
    int _val;
};


int main() {
    vector<int> vecInt {10, 9, 13, 24, 4, 7, 15, 19, 3, 8, 2};
    int n = std::count_if(vecInt.begin(), vecInt.end(), LessEqualValue(10));
    cout << n << endl;

    return 0;
}

輸出:

7

使用函數對象與使用函數指針相比較,有兩個方面的優點:

  1. 如果被重載的調用運算符是 inline 函數,則編譯器能夠執行內聯編譯,提供可能的性能優化
  2. 函數對象可以擁有任意數目的額外數據,可用來緩存操作中產生的結果

參考資料

《C++ Primer》第三版,中文版,Stanley B.Lippman 著,潘愛民等譯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章