C++学习之路: 函数适配器
引言:
函数适配器也是种模板技术, 通过绑定把函数绑定到适配器上实现函数调用, 并且可以修改参数,和移动参数的位置。功能强大
在这里简单介绍一下这种强大的工具
1. 对于普通函数, 直接把它的类型 <返回值 (参数1, 参数2,.......)> 如此填入 适配器当做函数类型即可
function<返回值 (参数1, 参数2,.......)> pf = &func ;
这样定义, pf就变成了func函数, 可以通过下例一样调用。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 7 void foo(const string &s) 8 { 9 cout << s << endl; 10 } 11 12 13 int main(int argc, const char *argv[]) 14 { 15 void (*pFunc) (const string &) = &foo; 16 pFunc("bar"); 17 18 function<void (const string&)> f = &foo; 19 f("bar"); 20 21 22 return 0; 23 }
2) 双参数普通函数的例子
与上例没什么不同, 不过多了个参数。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 7 void foo(int i, double d) 8 { 9 cout << i << d << endl; 10 } 11 12 13 int main(int argc, const char *argv[]) 14 { 15 function<void (int, double)> f = &foo; 16 f(12, 4.5); 17 18 19 return 0; 20 }
3. 对于类内部的成员函数, 如果没有实例我们就无法访问其成员函数 所以我们必须采用一种强大的工具----》 bind
这里介绍下bind 的接口, 这个bind 不是linux下 绑定套接字的那个bind, 不要混淆, bind返回值是一个函数适配器, 参数bind(参数1:要绑定的函数, 参数2:第一个参数要适配的位置或者要填充的常量, 参数3:第2个参数要适配的位置或者要填充的常量, 第3个参数要适配的位置或者要填充的常量)
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 7 class Foo 8 { 9 public: 10 void foo(int i) { cout << i << endl; } 11 12 static void bar(double d) { cout << d << endl; } 13 14 }; 15 16 int main(int argc, const char *argv[]) 17 { 18 //mem_fun void (*)(Foo *, int) 19 Foo f; 20 (mem_fun(&Foo::foo))(&f, 123); 21 22 function<void (int)> pf = bind(&Foo::foo, 23 &f, 24 std::placeholders::_1); 25 pf(345); 26 27 function<void (Foo*, int)> pf2 = bind(&Foo::foo, 28 std::placeholders::_1, 29 std::placeholders::_2); 30 31 pf2(&f, 456); 32 33 function<void (int, Foo*)> pf3 = bind(&Foo::foo, 34 std::placeholders::_2, 35 std::placeholders::_1); 36 37 pf3(567, &f); 38 39 40 41 return 0; 42 }
4.对于非类的成员函数同样也可以使用bind来绑定 来达到缺省 参数, 参数调换位置的目的
我们可以通过几个小练习来熟悉一下bind的接口。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 using namespace std::placeholders; 7 8 void test(int i, double d, const string &s) 9 { 10 cout << "i = " << i << " d = " << d << " s = " << s << endl; 11 } 12 int main(int argc, const char *argv[]) 13 { 14 function<void (int, double, const string&)> f1 = &test; 15 f1(12, 3.14, "foo"); 16 17 //1.void (*)(int, double) 18 function<void (int, double)> f2 = 19 std::bind(&test, 20 _1, 21 _2, 22 "foo"); 23 24 //2.void (*)(double, int, const string &) 25 function<void (double, int, const string &)> f3 = 26 std::bind(&test, 27 _2, 28 _1, 29 _3); 30 31 //3.void (*)(const string &, int) 32 function<void (const string &, int)> f4 = 33 std::bind(&test, 34 _2, 35 3.4, 36 _1); 37 38 39 //4. void (*) (const string &, int, double) 40 function<void (const string&, int, double)> f5 41 = std::bind(&test, 42 _2, 43 _3, 44 _1); 45 46 //5. void (*)(int) 47 function<void (int)> f6 = 48 bind(&test, 49 _1, 50 3.4, 51 "bar"); 52 53 //6 void(*)(const string &) 54 function<void (const string &)> f7 = 55 bind(&test, 56 12, 57 4.5, 58 _1); 59 60 //7. void (*)() 61 function<void()> f8 = 62 bind(&test, 63 12, 64 4.5, 65 "bar"); 66 }
通过以上7个小练习,相信对于简单的函数适配器已经可以应付了。
完毕