内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

C++函數(shù)配接器-創(chuàng)新互聯(lián)

一、概述

創(chuàng)新互聯(lián)建站專業(yè)提供西部信息中心服務(wù),為用戶提供五星數(shù)據(jù)中心、電信、雙線接入解決方案,用戶可自行在線購(gòu)買(mǎi)西部信息中心服務(wù),并享受7*24小時(shí)金牌售后服務(wù)。

  配接器(adaptor)在STL組件的靈活運(yùn)用功能上,扮演著軸承、轉(zhuǎn)換器的角色,將一種容器或迭代器裝換或封裝成另一種容器或迭代器。adaptor這個(gè)概念,實(shí)際上是一種設(shè)計(jì)模式,其定義如下:

  將一個(gè)class的接口轉(zhuǎn)換為另一個(gè)class的接口,使原本因接口不兼容而不能合作的classes,可以一起運(yùn)作。

配接器按功能可以分為如下3類:

可以改變函數(shù)或仿函數(shù)接口的適配器,稱為仿函數(shù)適配器;

    針對(duì)容器的適配器,稱為容器適配器;

    針對(duì)迭代器的適配器,稱為迭代器適配器。

本博客只介紹仿函數(shù)適配器,在實(shí)際編程中比較常見(jiàn)。

二、什么是可配接對(duì)象

  什么是可配接對(duì)象?看到這句話可能還云里霧里的,真不太明白,下面通過(guò)一個(gè)很簡(jiǎn)單的給數(shù)組排序的例子來(lái)解釋一下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>     //ostream_iterator

using namespace std;

struct myLess
{
        bool operator()(int lhs, int rhs) const
        {   
                return lhs < rhs;
        }   
};

int main()
{
        int IntArray[] = {7,4,2,9,1};
        sort(IntArray, IntArray + sizeof(IntArray) / sizeof(int), myLess());
        copy(IntArray, IntArray + sizeof(IntArray) / sizeof(int), ostream_iterator<int>(cout, "\n"));
        return 0;
}
#程序執(zhí)行結(jié)果
[root@oracle Documents]# ./a.out 
1
2
4
7
9

  可以看到這個(gè)程序正確執(zhí)行了,現(xiàn)在我想讓程序內(nèi)的數(shù)組進(jìn)行降序。當(dāng)然你可以重新定義一個(gè)仿函數(shù),但是我想用一個(gè)更快捷的方法,那就是not2函數(shù)。

//修改排序那一行的函數(shù)
sort(IntArray, IntArray + sizeof(IntArray) / sizeof(int), not2(myLess()));

  但是我發(fā)現(xiàn)這樣是編譯不過(guò)的,為什么呢?這就回到我們的主題了,因?yàn)閙yLess不是一個(gè)可配接對(duì)象。那么如何讓它變成一個(gè)可配接對(duì)象呢,繼續(xù)往下看。

三、unary_function和binary_function

  為什么剛剛寫(xiě)的myLess對(duì)象是不可配接的呢?因?yàn)樗鄙賏rgument_type、first_argument_type、second_argument_type和result_type這些特殊類型的定義。而unary_function和binary_function則可以提供這些類型的定義。我們?cè)诙x仿函數(shù)的時(shí)候,只需繼承自這2個(gè)函數(shù),那么我們的仿函數(shù)就是可配接的對(duì)象了。由于unary_function和binary_function是STL提供的模版,所以必須要指定必要的參數(shù)類型。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>     //ostream_iterator
#include <functional>   //binary_function, not2

using namespace std;

//第一個(gè)參數(shù),第二個(gè)參數(shù),返回值
struct myLess : public binary_function<int, int, bool>
{
        bool operator()(int lhs, int rhs) const
        {   
                return lhs < rhs;
        }   
};

int main()
{
        int IntArray[] = {7,4,2,9,1};
        sort(IntArray, IntArray + sizeof(IntArray) / sizeof(int), not2(myLess()));
        copy(IntArray, IntArray + sizeof(IntArray) / sizeof(int), ostream_iterator<int>(cout, "\n"));
        return 0;
}
#程序執(zhí)行結(jié)果
[root@oracle Documents]# ./a.out 
9
7
4
2
1

  傳遞給unary_function和binary_function的模版參數(shù)正是函數(shù)子類的operator()的參數(shù)類型和返回值。如果operator()接受一個(gè)參數(shù),則使用unary_function<參數(shù), 返回值>;如果operator()接受兩個(gè)參數(shù),則使用binary_function<參數(shù)1, 參數(shù)2, 返回值>。

  一般情況下,傳遞給unary_function和binary_function的非指針類型需要去掉const和引用(&)部分。如下:

struct myLess : public binary_function<myClass, myClass, bool>
{
        bool operator()(const myClass &lhs, const myClass &rhs) const
        {   
                return lhs < rhs;
        }   
};

  但是以指針作為參數(shù)或返回值的函數(shù)子類,一般規(guī)則是,傳給unary_function和binary_function的類型與operator()的參數(shù)和返回類型完全相同。如下:

struct myLess : public binary_function<const myClass *, const myClass *, bool>
{
        bool operator()(const myClass *lhs, const myClass *rhs) const
        {   
                return lhs < rhs;
        }   
};

四、標(biāo)準(zhǔn)的函數(shù)配接器

1. not1和not2

  這2個(gè)配接器都是對(duì)可配接對(duì)象的否定。上面已經(jīng)介紹過(guò)使用方法了。那么什么時(shí)候用not1,什么時(shí)候用not2呢?

  如果可配接對(duì)象的operator()接受一個(gè)參數(shù)則使用not1;如果可配接對(duì)象的operator()接受兩個(gè)參數(shù)則使用not2。

2. bind1st和bind2nd

  bind1st表示我們綁定第一個(gè)參數(shù),bind2st表示我們綁定第二個(gè)參數(shù)。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>     //ostream_iterator
#include <functional>   //binary_function, bind1st

using namespace std;

struct myLess : public binary_function<int, int, bool>
{
        bool operator()(int lhs, int rhs) const
        {   
                return lhs < rhs;
        }   
};

int main()
{
        int IntArray[] = {7,4,2,9,1};
        vector<int> IntVec(IntArray, IntArray + sizeof(IntArray) / sizeof(int));
        IntVec.erase(remove_if(IntVec.begin(), IntVec.end(), bind1st(myLess(), 5)), IntVec.end());
        copy(IntVec.begin(), IntVec.end(), ostream_iterator<int>(cout, "\n"));
        return 0;
}
#程序執(zhí)行結(jié)果
[root@oracle Documents]# ./a.out 
4
2
1

  bind1st(myLess(), 5)相當(dāng)于把5賦值給lhs,那么表達(dá)式就變成 5 < rhs,所以7和9就被刪除了。

  如果把bind1st(myLess(), 5)改成bind2nd(myLess(), 5)),就相當(dāng)于把5賦值給rhs,那么表達(dá)式就變成 lhs < 5, 所以1、2和4就被刪除了。bind1st(myLess(), 5) 等于 not1(bind2nd(myLess(), 5)))。

五、ptr_fun、mem_fun和mem_fun_ref

  我們已經(jīng)知道仿函數(shù)通過(guò)繼承unary_function和binary_function可以變成可配接對(duì)象,那么普通函數(shù)或者類的成員函數(shù)如何變成可配接對(duì)象呢?這就需要用到標(biāo)題中的三個(gè)函數(shù)了。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>     //ostream_iterator
#include <functional>   //not2

using namespace std;

class sortObj
{
public:
        bool memComp(const sortObj *other)
        {   
                return *this < *other;
        }   

        bool memComp_const(const sortObj &other) const
        {   
                return *this < other;
        }   
public:
        sortObj(int v) : value(v){}
        ~sortObj(){}

        friend bool operator<(const sortObj &lhs, const sortObj &rhs)
        {   
                return lhs.value < rhs.value;
        }

        friend ostream & operator<<(ostream &os, const sortObj &obj)
        {
                return os << obj.value << endl;
        }
private:
        int value;
};

bool sortFun(const sortObj &lhs, const sortObj &rhs)
{
        return lhs < rhs;
}

//把指針轉(zhuǎn)換成對(duì)象
sortObj & ptrToObj(sortObj *ptr)
{
        return *ptr;
}

int main()
{
        sortObj objArray[] = {
                sortObj(7),
                sortObj(4),
                sortObj(2),
                sortObj(9),
                sortObj(1)
        };
        vector<sortObj> objVec(objArray, objArray + sizeof(objArray) / sizeof(sortObj));

        //配接普通函數(shù)(降序)
        sort(objVec.begin(), objVec.end(), not2(ptr_fun(sortFun)));
        copy(objVec.begin(), objVec.end(), ostream_iterator<sortObj>(cout, ""));
        cout << endl;

        srand(time(NULL));
        random_shuffle(objVec.begin(), objVec.end());   //打亂順序
        //配接對(duì)象的成員函數(shù)(升序)
        sort(objVec.begin(), objVec.end(), mem_fun_ref(&sortObj::memComp_const));
        copy(objVec.begin(), objVec.end(), ostream_iterator<sortObj>(cout, ""));
        cout << endl;

        //配接指針的成員函數(shù)(降序)
        vector<sortObj *> objVecPtr;
        objVecPtr.push_back(new sortObj(7));    //內(nèi)存泄漏了,不要在意這些細(xì)節(jié)
        objVecPtr.push_back(new sortObj(4));
        objVecPtr.push_back(new sortObj(2));
        objVecPtr.push_back(new sortObj(9));
        objVecPtr.push_back(new sortObj(1));
        sort(objVecPtr.begin(), objVecPtr.end(), not2(mem_fun(&sortObj::memComp)));
        transform(objVecPtr.begin(), objVecPtr.end(), ostream_iterator<sortObj>(cout, ""), ptrToObj);

        return 0;
}

  上述代碼中,首先調(diào)用not2(ptr_fun(sortFun)),用ptr_fun對(duì)普通函數(shù)sortFun進(jìn)行配接;其次調(diào)用mem_fun_ref(&sortObj::memComp_const)和not2(mem_fun(&sortObj::memComp))對(duì)sortObj類的成員函數(shù)進(jìn)行配接。這里有的童鞋可能有疑問(wèn):memComp明明只有一個(gè)形參,為什么用not2而不是not1?成員函數(shù)在別調(diào)用的時(shí)候,會(huì)自動(dòng)傳進(jìn)this指針的,所以這里還是兩個(gè)參數(shù)。

  mem_fun和mem_fun_ref都是對(duì)類的成員函數(shù)進(jìn)行配接,那么它們有什么區(qū)別嗎?相信細(xì)心的童鞋已經(jīng)看出來(lái)了,當(dāng)容器中存放的是對(duì)象實(shí)體的時(shí)候用mem_fun_ref,當(dāng)容器中存放的是對(duì)象的指針的時(shí)候用mem_fun。

  mem_fun和mem_fun_ref有一個(gè)很大的弊端:它們只能接收0個(gè)或1個(gè)參數(shù)(不算this指針)。這個(gè)實(shí)在有點(diǎn)局限。新的bind函數(shù)模板可以用于任何函數(shù)、函數(shù)指針、成員函數(shù)、函數(shù)對(duì)象、模板函數(shù)、lambda表達(dá)式,還可以嵌套bind。

六、bind

  上面介紹的這些配接器都是C++11之前使用的,在C++11中這些配接器已經(jīng)被廢棄了,改成使用bind函數(shù)。如果想在C++11之前的版本中使用這個(gè)函數(shù),有Linux下有兩種方法。

1. 包含<functional>頭文件,在編譯的時(shí)候增加編譯參數(shù)-std=c++0x,那么就可以使用std::bind了

2. 包含#include <tr1/functional> 頭文件,直接可以使用std::tr1::bind了。

  在bind中有2種方式可以把值傳遞進(jìn)bind函數(shù)中,一種是預(yù)先綁定的參數(shù),這個(gè)參數(shù)是通過(guò)pass-by-value傳遞進(jìn)去的;另一種是不預(yù)先綁定的參數(shù),這種參數(shù)是通過(guò)placeholders占位符傳遞進(jìn)去的,它是pass-by-reference的。

  上述代碼中的3個(gè)排序函數(shù)配接器可以替換成下面這樣的bind,如下:

//綁定普通函數(shù)(降序)
sort(objVec.begin(), objVec.end(), tr1::bind(sortFun, tr1::placeholders::_2, tr1::placeholders::_1));
//綁定類對(duì)象的成員函數(shù)(升序)
sort(objVec.begin(), objVec.end(), tr1::bind(&sortObj::memComp_const, tr1::placeholders::_1, tr1::placeholders::_2));
//綁定類指針的成員函數(shù)(降序)
sort(objVecPtr.begin(), objVecPtr.end(), tr1::bind(&sortObj::memComp, tr1::placeholders::_2, tr1::placeholders::_1));

  注意,在上面的例子中,我使用了not2方法對(duì)結(jié)果進(jìn)行倒序。但是bind和not2是不兼容的,實(shí)現(xiàn)倒序的方法也很簡(jiǎn)單,先傳遞placeholders::_2,再傳遞placeholders::_1就可以實(shí)現(xiàn)了。

bind的其他用法實(shí)例:

#include <iostream>
#include <tr1/memory>
#include <tr1/functional>

using namespace std;
using namespace std::tr1;

int main()
{
        //嵌套bind
        //(x + y) * x
        function<int (int, int)> func = bind(multiplies<int>(), 
                                bind(plus<int>(), placeholders::_1, placeholders::_2), 
                                placeholders::_1);
        cout << func(2, 3) << endl;

        //reference_wrapper<T>類型, 實(shí)現(xiàn)綁定引用
        int x = 10; 
        function<int ()> funcMinus = bind(minus<int>(), 100, cref(x));
        cout << funcMinus() << endl;    //輸出90

        x = 50; 
        cout << funcMinus() << endl;    //輸出50
        return 0;
}

  function的<>中定義的是綁定后的函數(shù)的原型,即func和funcMinus的函數(shù)原型

#程序執(zhí)行結(jié)果
[root@oracle Documents]# ./a.out 
10
90
50

七、內(nèi)置仿函數(shù)

上面介紹bind的例子中已經(jīng)使用過(guò)C++內(nèi)置的仿函數(shù),這里再進(jìn)行一下匯總

 1)算術(shù)類仿函數(shù)

 加:plus<T>     接收2個(gè)參數(shù)

 減:minus<T>     接收2個(gè)參數(shù)

 乘:multiplies<T>   接收2個(gè)參數(shù)

 除:divides<T>    接收2個(gè)參數(shù)

 模?。簃odulus<T>    接收2個(gè)參數(shù)

 否定:negate<T>    接收1個(gè)參數(shù)(正數(shù)變負(fù)數(shù),負(fù)數(shù)變正數(shù))

 2)關(guān)系運(yùn)算類仿函數(shù)

 等于:equal_to<T>      接收2個(gè)參數(shù)

 不等于:not_equal_to<T>   接收2個(gè)參數(shù)

 大于:greater<T>      接收2個(gè)參數(shù)

 大于等于:greater_equal<T>  接收2個(gè)參數(shù)

 小于:less<T>       接收2個(gè)參數(shù)

 小于等于:less_equal<T>   接收2個(gè)參數(shù)

 3)邏輯運(yùn)算仿函數(shù)

 邏輯與:logical_and<T>   接收2個(gè)參數(shù)

 邏輯或:logical_or<T>   接收2個(gè)參數(shù)

 邏輯否:logical_no<T>   接收2個(gè)參數(shù)

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

新聞標(biāo)題:C++函數(shù)配接器-創(chuàng)新互聯(lián)
鏈接URL:http://www.rwnh.cn/article46/geghg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、小程序開(kāi)發(fā)、軟件開(kāi)發(fā)、云服務(wù)器、品牌網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開(kāi)發(fā)
方正县| 瑞安市| 云霄县| 庆云县| 文昌市| 渭源县| 九龙坡区| 尼勒克县| 马鞍山市| 南漳县| 荥阳市| 闵行区| 鄂托克前旗| 江达县| 陕西省| 大洼县| 洪湖市| 乌恰县| 新和县| 麻城市| 舒城县| 大庆市| 沂水县| 水富县| 鹿邑县| 通榆县| 娄烦县| 确山县| 维西| 鄄城县| 玉门市| 阳曲县| 杭锦后旗| 综艺| 若尔盖县| 阿拉尔市| 江源县| 濉溪县| 凤凰县| 南川市| 禄丰县|