阿里巴巴做網(wǎng)站找誰泰州百度seo公司
文章目錄
- 包裝器
- 1、functional
- 2、綁定
這一篇比較簡短,只是因為后要寫異常和智能指針,所以就把它單獨放在了一篇博客,后面新開幾篇博客來寫異常和智能指針
包裝器
1、functional
包裝器是一個類模板,對可調(diào)用對象類型進行再封裝適配,可調(diào)用對象,比如函數(shù)指針,lambda等。包裝器的頭文件是functional。
template <class T> function;
template <class Ret, class... Args>
class function<Ret(Args...)>
模板參數(shù)說明:
Ret:被調(diào)用函數(shù)的返回類型
Args...:被調(diào)用函數(shù)的形參
實際使用
int f(int a, int b)
{cout << "f" << endl;return a + b;
}struct Functor
{
public:int operator() (int a, int b){cout << "Functor" << endl;return a + b;}
};int main()
{//int(*pf1)(int, int) = f;函數(shù)指針function<int(int, int)> f1 = f;function<int(int, int)> f2 = Functor();function<int(int, int)> f3 = [](int a, int b) {cout << "lambda" << endl;return a + b; };cout << f1(1, 2) << endl;cout << f2(10, 20) << endl;cout << f3(100, 200) << endl;return 0;
}
三個int,第一個是函數(shù)返回值類型,后兩個是參數(shù)類型。包裝起包裝起來的就可以傳給模板參數(shù)
map<string, function<int(int, int)>> opFuncMap;opFuncMap["函數(shù)指針"] = f1;opFuncMap["仿函數(shù)"] = Functor();opFuncMap["lambda"] = [](int a, int b) {cout << "lambda" << endl;return a + b;};cout << opFuncMap["lambda"](1, 2) << endl;
看一個題
逆波蘭表達式求值
給你一個字符串數(shù)組 tokens ,表示一個根據(jù) 逆波蘭表示法 表示的算術(shù)表達式。
請你計算該表達式。返回一個表示表達式值的整數(shù)。
注意:
有效的算符為 ‘+’、‘-’、‘*’ 和 ‘/’ 。
每個操作數(shù)(運算對象)都可以是一個整數(shù)或者另一個表達式。
兩個整數(shù)之間的除法總是 向零截斷 。
表達式中不含除零運算。
輸入是一個根據(jù)逆波蘭表示法表示的算術(shù)表達式。
答案及所有中間計算結(jié)果可以用32位整數(shù)表示。
之前的寫法
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(auto& str : tokens){if(str == "+" || str == "-" || str == "/" || str == "*"){int right = st.top();st.pop();int left = st.top();st.pop();switch(str[0]){case '+':st.push(left+right);break;case '-':st.push(left-right);break;case '*':st.push(left*right);break;case '/':st.push(left/right);break;}}else{st.push(stoi(str));}}return st.top();}
};
用包裝器后
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;map<string, function<int(int, int)>> opFuncMap = {{"+", [](int a, int b){return a + b; }},{"-", [](int a, int b){return a - b; }},{"*", [](int a, int b){return a * b; }},{"/", [](int a, int b){return a / b; }}};//這里就是map的初始化,用C++11的列表初始化for(auto str : tokens){if(opFuncMap.count(str)){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};
包裝器也可以包裝成員函數(shù)。
class Plus
{
public:static int plus1(int a, int b){return a + b;}double plus2(double a, double b){return (a + b) * _rate;}
private:int _rate = 2;
};int main()
{
class Plus
{
public:Plus(int rate = 2):_rate(rate){}static int plus1(int a, int b){return a + b;}double plus2(double a, double b){return (a + b) * _rate;}
private:int _rate = 2;
};int main()
{function<int(int, int)> f1 = Plus::plus1;function<int(Plus, double, double)> f2 = &Plus::plus2;cout << f1(1, 2) << endl;cout << f2(Plus(), 20, 20) << endl;Plus p1(3);cout << f2(p1, 20, 20) << endl;return 0;
}
靜態(tài)成員函數(shù)可以直接調(diào)用,而非靜態(tài)的需要在第一個位置加上類名,因為有this指針,然后后面的Plus前加上&,靜態(tài)函數(shù)也可以加上這個&,使用這個函數(shù)的時候,非靜態(tài)需要在第一個參數(shù)位置放上類的對象,可以是匿名對象,如果在聲明f2時,傳的是*Plus,那么下面調(diào)用時就必須傳對象的地址,所以就不能傳匿名對象的地址,因為右值無法取地址。
包裝器本質(zhì)上是仿函數(shù),f1,f2,f3就是對象,然后調(diào)用operator(),傳過去參數(shù),然后operator()再去調(diào)用對應(yīng)函數(shù),傳類的對象就用對象來調(diào)用,傳指針就指針來調(diào)用。
2、綁定
綁定是一個函數(shù)模板,用來調(diào)整參數(shù)。綁定是一個通用的函數(shù)適配器,接受一個可調(diào)用對象,可調(diào)用對象就是三個,函數(shù)指針、lambda、仿函數(shù),生成一個新的可調(diào)用對象來適配。
bind函數(shù)第一個參數(shù)是一個萬能引用,左右值都可傳,然后后面的是占位符,_1表示第一個參數(shù),_2表示第二個參數(shù),以此類推,這些占位符是一個placeholders空間里。
int Print(int a, int b)
{cout << a << " ";cout << b << endl;
}int main()
{Print(10, 20);auto RP = bind(Print, placeholders::_2, placeholders::_1);RP(10, 20);//再次調(diào)用就換了順序了。return 0;
}
如果bind寫著_1在_2前面,那就沒換順序,要換順序占位符就得對應(yīng)著寫。bind函數(shù)會返回一個對象,我們可以用auto來推演類型,還可以用function<void(int, int)>。實際調(diào)用的還是Print,不過適配器就是套了一個殼。
綁定真正有用的是改變參數(shù)個數(shù)
用這段代碼做例子
class Sub
{
public:Sub(int rate):_rate(rate){}int func(int a, int b){return (a - b) * _rate;}
private:int _rate;
};class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;map<string, function<int(int, int)>> opFuncMap ={{"+", [](int a, int b) {return a + b; }},{"-", [](int a, int b) {return a - b; }},{"*", [](int a, int b) {return a * b; }},{"/", [](int a, int b) {return a / b; }}};//這里就是map的初始化,用C++11的列表初始化for (auto str : tokens){if (opFuncMap.count(str)){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};int main()
{function<int(Sub, int, int)> fSub = &Sub::func;fSub(Sub(1), 10, 20);return 0;
}
這是上面包裝器的寫法。這樣的寫法無法給opFuncMap傳fSub對象,因為參數(shù)個數(shù)不一致,這時候就是綁定的作用體現(xiàn)了。
function<int(int, int)> fSub = bind(&Sub::func, Sub(1), placeholders::_1, placeholders::_2);fSub(10, 20);
把Sub(1)對象顯式地傳給func函數(shù),順序沒有變,只是第一個參數(shù)顯示傳,剩下兩個就從_1開始排順序。也可以對其他參數(shù)來綁定。
function<int(int, int)> fSub = bind(&Sub::func, placeholders::_1, 10, placeholders::_2);fSub(Sub(1), 20);
本篇gitee
結(jié)束。