最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11學(xué)習(xí)之包裝器解析

 更新時(shí)間:2023年02月13日 10:55:36   作者:張小姐的貓  
function包裝器?也叫作適配器。C++中的function本質(zhì)是一個(gè)類模板,也是一個(gè)包裝器。本文就來和大家聊聊我們?yōu)槭裁葱枰猣unction呢

概念

function包裝器 也叫作適配器。C++中的function本質(zhì)是一個(gè)類模板,也是一個(gè)包裝器。

那么我們來看看,我們?yōu)槭裁葱枰猣unction呢?

包裝器定義式:

// 類模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;

模板參數(shù)說明:

  • Ret: 是被包裝的可調(diào)用對(duì)象的返回值類型
  • Args... :是被包裝的可調(diào)用對(duì)象的形參類型

function包裝器可以對(duì)可調(diào)用對(duì)象進(jìn)行包裝,包括函數(shù)指針、函數(shù)名、仿函數(shù)(函數(shù)對(duì)象)、lambda表達(dá)式

int f(int a, int b)
{
	return a + b;
}

struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};

class Plus
{
public:
	//靜態(tài) vs 非靜態(tài)
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	function<int(int, int)> f1 = f;
	f1(1, 2);

	function<int(int, int)> f2 = Functor();
	f2(1, 2);

	function<int(int, int)> f3 = Plus::plusi;
	f3(1, 2);

	//非靜態(tài)成員函數(shù)    要 + 對(duì)象
	function<double(Plus, double, double)> f4 = &Plus::plusd;
	f4(Plus(), 1.1, 2.2);

	return 0;
}

注意事項(xiàng):

取靜態(tài)成員函數(shù)的地址可以不用取地址運(yùn)算符“&”,但取非靜態(tài)成員函數(shù)的地址必須使用取地址運(yùn)算符“&”

非靜態(tài)成員函數(shù)在調(diào)用的時(shí)候要 + 對(duì)象,因?yàn)榉庆o態(tài)成員函數(shù)的第一個(gè)參數(shù)是隱藏this指針,所以在包裝時(shí)需要指明第一個(gè)形參的類型為類的類型。

類型統(tǒng)一

對(duì)于以下函數(shù)模板useF:

  • 傳入該函數(shù)模板的第一個(gè)參數(shù)可以是任意的可調(diào)用對(duì)象,比如函數(shù)指針、仿函數(shù)、lambda表達(dá)式等
  • useF中定義了靜態(tài)變量count,并在每次調(diào)用時(shí)將count的值和地址進(jìn)行了打印,可判斷多次調(diào)用時(shí)調(diào)用的是否是同一個(gè)useF函數(shù)。

代碼如下:

template<class F, class T>
T useF(F f, T x)
{
    static int count = 0;
    cout << "count:" << ++count << endl;
    cout << "count:" << &count << endl;
    return f(x);
}

在不使用包裝器,直接傳入對(duì)象的時(shí)候,會(huì)實(shí)例化出三份

double f(double i)
{
	return i / 2;
}
struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};
int main()
{
	//函數(shù)指針
	cout << useF(f, 11.11) << endl;

	//仿函數(shù)
	cout << useF(Functor(), 11.11) << endl;

	//lambda表達(dá)式
	cout << useF([](double d)->double{return d / 4; }, 11.11) << endl;
	return 0;
}

輸出結(jié)果如下:

由于函數(shù)指針、仿函數(shù)、lambda表達(dá)式是不同的類型,因此useF函數(shù)會(huì)被實(shí)例化出三份,三次調(diào)用useF函數(shù)所打印count的地址也是不同的。

  • 但實(shí)際這里其實(shí)沒有必要實(shí)例化出三份useF函數(shù),因?yàn)槿握{(diào)用useF函數(shù)時(shí)傳入的可調(diào)用對(duì)象雖然是不同類型的,但這三個(gè)可調(diào)用對(duì)象的返回值和形參類型都是相同的
  • 這時(shí)就可以用包裝器分別對(duì)著三個(gè)可調(diào)用對(duì)象進(jìn)行包裝,然后再用這三個(gè)包裝后的可調(diào)用對(duì)象來調(diào)用useF函數(shù),這時(shí)就只會(huì)實(shí)例化出一份useF函數(shù)
  • 根本原因就是因?yàn)榘b后,這三個(gè)可調(diào)用對(duì)象都是相同的function類型,因此最終只會(huì)實(shí)例化出一份useF函數(shù),該函數(shù)的第一個(gè)模板參數(shù)的類型就是function類型的

包裝后代碼如下:

int main()
{
	// 函數(shù)指針
	function<double(double)> f1 = f;
	cout << useF(f1, 11.11) << endl;

	// 函數(shù)對(duì)象
	function<double(double)> f2 = Functor();
	cout << useF(f2, 11.11) << endl;

	// lamber表達(dá)式
	function<double(double)> f3 = [](double d)->double { return d / 4; };
	cout << useF(f3, 11.11) << endl;

	return 0;
}

例題:求解逆波蘭表達(dá)式

題目:

解題思路:

  • 首先定義一個(gè)棧,依次遍歷所給字符串
  • 遇到數(shù)字,直接入棧,遇到操作符,則從棧定拋出兩個(gè)數(shù)字進(jìn)行對(duì)應(yīng)的運(yùn)算,并將運(yùn)算后得到的結(jié)果壓入棧中
  • 所給字符串遍歷完畢后,棧頂?shù)臄?shù)字就是逆波蘭表達(dá)式的計(jì)算結(jié)果

此處的包裝器:

  • 建立各個(gè)運(yùn)算符與其對(duì)應(yīng)需要執(zhí)行的函數(shù)之間的映射關(guān)系,當(dāng)需要執(zhí)行某一運(yùn)算時(shí)就可以直接通過運(yùn)算符找到對(duì)應(yīng)的函數(shù)進(jìn)行執(zhí)行
  • 當(dāng)運(yùn)算類型增加時(shí),就只需要建立新增運(yùn)算符與其對(duì)應(yīng)函數(shù)之間的映射關(guān)系即可(其他代碼不用動(dòng))
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        map<string, function<long long(long long, long long)>> opfuncMap = 
        {
            //自動(dòng)構(gòu)造pair ~ 初始化列表構(gòu)造
            {"+", [](long long a , long long b){return a + b;}},
            {"-", [](long long a , long long b){return a - b;}},
            {"*", [](long long a , long long b){return a * b;}},
            {"/", [](long long a , long long b){return a / b;}},
        };


        for(auto& str : tokens)
        {
            if(opfuncMap.count(str))
            {
                //操作符 :出棧(先出右,再出左)
                long long right = st.top();
                st.pop();
                long long left = st.top();
                st.pop();
                st.push(opfuncMap[str](left, right));
            }
            else
            {
                //操作數(shù):入棧
                st.push(stoll(str));
            }
        }
        return st.top();
    }
};

包裝器的意義

將可調(diào)用對(duì)象的類型進(jìn)行統(tǒng)一,便于我們對(duì)其進(jìn)行統(tǒng)一化管理。

包裝后明確了可調(diào)用對(duì)象的返回值和形參類型,更加方便使用者使用。

bind 包裝器

bind 是一種函數(shù)包裝器,也叫做適配器。它可以接受一個(gè)可調(diào)用對(duì)象,生成一個(gè)新的可調(diào)用對(duì)象來“適應(yīng)”原對(duì)象的參數(shù)列表,C++ 中的 bind 本質(zhì)還是一個(gè)函數(shù)模板

bind函數(shù)模板的原型如下:

template <class Fn, class... Args>
/* unspecified */ bind(Fn&& fn, Args&&... args);
template <class Ret, class Fn, class... Args>
/* unspecified */ bind(Fn&& fn, Args&&... args);

模板參數(shù)說明:

  • fn:可調(diào)用對(duì)象
  • args...:要綁定的參數(shù)列表:值或占位符

調(diào)用bind的一般形式

auto newCallable = bind(callable, arg_list);

callable:需要包裝的可調(diào)用對(duì)象

newCallable:生成的新的可調(diào)用對(duì)象

arg_list:逗號(hào)分隔的參數(shù)列表,對(duì)應(yīng)給定的 callable 的參數(shù),當(dāng)調(diào)用 newCallable時(shí),newCallable 會(huì)調(diào)用 callable,并傳給它 arg_list 中的參數(shù)

_1 _2 ... 是定義在placeholders命名空間中,代表綁定函數(shù)對(duì)象的形參;_1代表第一個(gè)形參,_2代表第二個(gè)形參 …

舉例:

using namespace placeholders;
int x = 2, y = 10;
Div(x, y);

auto bindFun1 = bind(Div, _1, _2);

bind 綁定固定參數(shù)

原本傳入的參數(shù)要求是要3個(gè),現(xiàn)在只需要輸入兩個(gè)參數(shù),因?yàn)榻壎斯潭ǖ暮瘮?shù)對(duì)象

using namespace placeholders;

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	//function<int(Sub, int, int)> fsub = &Sub::sub;
	function<int(int, int)> fsub = bind(&Sub::sub, Sub(), _1, _2);
}

想把Mul函數(shù)的第三個(gè)參數(shù)固定綁定為1.5,可以在綁定時(shí)將參數(shù)列表的placeholders::_3設(shè)置為1.5。比如:

int Mul(int a, int b, int rate)
{
	return a * b * rate;
}

int main()
{
	function<int(int, int)> fmul = bind(Mul, _1, _2, 1.5);
}

調(diào)整傳參順序

對(duì)于 Sub 類中的 sub 函數(shù),因?yàn)?sub 的第一個(gè)參數(shù)是隱藏的 this 指針,如果想要在調(diào)用 sub 時(shí)不用對(duì)象進(jìn)行調(diào)用,那么可以將 sub 的第一個(gè)參數(shù)固定綁定為一個(gè) Sub 對(duì)象:

using namespace placeholders;

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	//綁定固定參數(shù)
	function<int(int, int)> func = bind(&Sub::sub, Sub(), _1, _2);
	cout << func(1, 2) << endl; 
	return 0;
}

此時(shí)調(diào)用對(duì)象時(shí)就只需要傳入用于相減的兩個(gè)參數(shù),因?yàn)樵谡{(diào)用時(shí)會(huì)固定幫我們傳入一個(gè)匿名對(duì)象給 this 指針。

如果想要將 sub 的兩個(gè)參數(shù)順序交換,那么直接在綁定時(shí)將 _1 和_2 的位置交換一下就行了:

using namespace placeholders;

class Sub
{
public:
    int sub(int a, int b)
    {
        return a - b;
    }
};
int main()
{
    //綁定固定參數(shù)
    function<int(int, int)> func = bind(&Sub::sub, Sub(), _2, _1);
    cout << func(1, 2) << endl; 
    return 0;
}

其原理:第一個(gè)參數(shù)會(huì)傳給_1,第二個(gè)參數(shù)會(huì)傳給 _2,因此可以在綁定時(shí)通過控制 _n 的位置,來控制第 n 個(gè)參數(shù)的傳遞位置

bind包裝器的意義

1.將一個(gè)函數(shù)的某些參數(shù)綁定為固定的值,讓我們?cè)谡{(diào)用時(shí)可以不用傳遞某些參數(shù)。

2.可以對(duì)函數(shù)參數(shù)的順序進(jìn)行靈活調(diào)整。

以上就是C++11學(xué)習(xí)之包裝器解析的詳細(xì)內(nèi)容,更多關(guān)于C++11包裝器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解C++程序中定義struct結(jié)構(gòu)體的方法

    詳解C++程序中定義struct結(jié)構(gòu)體的方法

    C++中同樣擁有C語言中的結(jié)構(gòu)體,下面就來詳解C++程序中定義struct結(jié)構(gòu)體的方法,需要的朋友可以參考下
    2016-05-05
  • C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(Map實(shí)現(xiàn))

    C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(Map實(shí)現(xiàn))

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言數(shù)組實(shí)現(xiàn)打磚塊游戲

    C語言數(shù)組實(shí)現(xiàn)打磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了C語言數(shù)組實(shí)現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C/C++字符串查找函數(shù)全面了解

    C/C++字符串查找函數(shù)全面了解

    下面小編就為大家?guī)硪黄狢/C++字符串查找函數(shù)全面了解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • C++在非面向?qū)ο蠓矫鎸?duì)C語言的擴(kuò)充

    C++在非面向?qū)ο蠓矫鎸?duì)C語言的擴(kuò)充

    C++是一種面向?qū)ο缶幊陶Z言,但它也可以作為C語言的擴(kuò)展語言。在C++中,我們可以使用非面向?qū)ο蠓矫娴奶匦詠頂U(kuò)展C語言。在本文中,我們將討論C++在非面向?qū)ο蠓矫鎸?duì)C語言的擴(kuò)充
    2023-05-05
  • MFC模擬實(shí)現(xiàn)自定義消息發(fā)送

    MFC模擬實(shí)現(xiàn)自定義消息發(fā)送

    在MFC框架下,有很多系統(tǒng)已經(jīng)定義好的消息,例如ON_WM_LBUTTONDOWN()、ON_WM_MBUTTONDOWN()等等。本文將利用這些定義好的消息模擬實(shí)現(xiàn)一下消息發(fā)送,需要的可以參考一下
    2022-01-01
  • c++ bitset詳解

    c++ bitset詳解

    這篇文章主要介紹了C++ bitset用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • 基于QT制作一個(gè)倒計(jì)時(shí)軟件

    基于QT制作一個(gè)倒計(jì)時(shí)軟件

    這篇文章主要為大家詳細(xì)介紹了如何基于QT制作一個(gè)簡單的倒計(jì)時(shí)軟件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • Cocos2d-x UI開發(fā)之CCControlSwitch控件類使用實(shí)例

    Cocos2d-x UI開發(fā)之CCControlSwitch控件類使用實(shí)例

    這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlSwitch控件類使用實(shí)例,本文代碼中含大量注釋講解了CCControlSwitch控件類的使用,需要的朋友可以參考下
    2014-09-09
  • 盤點(diǎn)分析C語言中少見卻強(qiáng)大的字符串函數(shù)

    盤點(diǎn)分析C語言中少見卻強(qiáng)大的字符串函數(shù)

    這篇文章主要為大家盤點(diǎn)及分析C語言中少見卻強(qiáng)大的字符串函數(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02

最新評(píng)論

新民市| 定边县| 自贡市| 高安市| 略阳县| 焦作市| 颍上县| 岐山县| 昌宁县| 宝鸡市| 翁源县| 柞水县| 白山市| 丰镇市| 上栗县| 桐柏县| 台南县| 杭锦旗| 蓝田县| 芒康县| 新绛县| 正蓝旗| 乌兰察布市| 泾源县| 社会| 休宁县| 保德县| 临西县| 论坛| 大宁县| 海南省| 冀州市| 房产| 洛浦县| 电白县| 砚山县| 扶绥县| 石渠县| 荥阳市| 诏安县| 淮滨县|