c++重載小括號,實現仿函數


重載 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關鍵字抑制隱式的轉換構造函數,讓程序只調用類型轉換函數。但是,我們無法抑制隱式的類型轉換函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM