C++ 函數對象

函數對象實質上是一個實現了operator()--括號操做符重載--的類。它與函數指針用法同樣,可是它有一個優勢,函數指針不能夠傳遞附加數據過去,可是在函數對象中,咱們能夠傳遞附加數據過去。ios

 

先講解下運算符重載吧,對於運算符函數咱們有兩種定義方式,算法

1,若是此函數是屬於一個類的成員函數,那麼咱們是這麼定義的:參考<< ,以下:函數

ostream & operator<<(const string & str);spa

咱們能夠經過這樣的形式來調用:cout << str ;指針

注意:按正常狀況下,對於一個類A中的函數,咱們應該這樣調用此類中的成員函數:A.func() ,可是對於運算符重載函數,咱們並非這樣,如同cout << str ,cout就是調用<<運算符的一個對象,這裏沒有點號了。code

2,若是此函數並不是另外一個類中的成員函數,而是一個普通函數,那麼咱們應該這麼定義:對象

type operator(a, b); type是返回類型string

咱們能夠這樣使用:a operator b;it

 

因此對於重載了()運算符的函數對象類,若是經過函數對象類定義了一個對象a,那麼咱們這樣使用對象a的「()」運算符重載:io

a();

對,就這樣,代表此「()」是對象a中的成員函數

若是要傳遞參數的話,能夠這樣:a(type name, ......);  name就是傳遞到「()」重載函數中的參數

 

下面看兩個例子:

第一個是演示函數對象怎麼使用的:

#include <iostream>
#include <string>

using namespace std;

class funObject {//定義一個函數對象
public:
    funObject(const char *name) : str(name)//構造函數,在構造函數中傳遞一個參數過來 
    {
        cout << str << endl;
    }
    void operator()(char *name) {//重載()運算符
       if (!str.empty()) 
           cout << str;//打印函數對象中私有的數據
       cout << name << endl;//打印()函數中傳遞過來的實參
    }
private:
    string str;
};

int main()
{
    //funObject("hello");//僅僅調用了一下函數對象的構造函數
    funObject obj("hello");//定義了一個函數對象類的一個對象,並傳遞了一個附加數據
    obj(" kitty");調用obj對象的()函數,實參是"kitty".
    return 0;
}

運行結果:

[chengyang@localhost functionObject]$ ./test2
hello
hello kitty


函數對象常常用於C++標準算法中,做爲一個操做函數參數傳遞

 

另外,函數對象還有一個函數指針沒法匹敵的用法:能夠用來封裝類成員函數指針!


由於函數對象能夠攜帶附加數據,而成員函數指針缺乏一個類實體(類實例)指針來調用,所以,能夠把類實體指針給函數對象保存起來,就能夠用於調用對應類實體成員函數了。

看以下代碼:

#include <iostream>

using namespace std;

class A {
public:
    void print(const char *name) //一個類中的函數,咱們要經過函數對象將其封裝
    {cout << "hello " << name << "!" << endl;}
};


template<typename T>
class funObject {//函數對象
public:
    funObject(void(T::*f)(const char *), T *obj) : pFunc(f), pObj(obj){}//構造函數,傳遞附加數據
    void operator()(const char *name)//經過此函數封裝某一個類的函數
    {
      (pObj->*pFunc)(name);//調用某一個類的一個對象的一個函數成員,這就是封裝
    }
private:
    void(T::*pFunc)(const char *);//儲存某一個類中的函數
    T *pObj;//儲存某一個類的一個對象
};

int main()
{
    A a;
    funObject<A> call(&A::print, &a);//定義一個函數對象類的對象,傳遞一個類的對象和一個類的某個成員函數進去
    call("kitty");//調用封裝對象某個對象的()函數,在此函數中,咱們又進而經過某一個類的一個對象調用此類的一個成員函數
    return 0;
}

運算結果以下:

[chengyang@localhost functionObject]$ ./test1
hello kitty!
相關文章
相關標籤/搜索