模板函数:
template<typename T>T sum(T a, T b) { return a + b; }int main() {function<int(int, int)> func1 = sum<int>;//调用func1.operator()(int, int) ==> int sum(int, int);cout << func1(3, 5) << endl; //输出8return 0;}
lambda表达式:
int main() {function<int(int, int)> func1 = [](int a, int b)->int { return a + b; };cout << func1(3, 5) << endl; //打印8 调用func1.operator()(int, int) ==> 调用lambda表达式返回求和结果return 0;}
函数对象:
class PrintAdd1 {public:void operator()(int left, int right) {cout << "sum : " << left + right << endl;}};int main() {function<void(int, int)> func1 = PrintAdd1(); //调用默认无参构造函数创建匿名类对象给func1func1(3, 5); //func1.operator()(int, int) ==> 调用void PrintAdd1.operator(int, int)return 0;}
模板函数对象:
template<typename T>class PrintAdd2 {public:void operator()(T left, T right) {cout << "sum : " << left + right << endl;}};int main() {function<void(int, int)> func1 = PrintAdd2<int>(); //调用默认无参构造函数创建匿名模板类对象给func1func1(3, 5); //func1.operator()(int, int) ==> 调用void PrintAdd2.operator()(int, int)return 0;}
类静态成员函数:
class StaticClass1 {public:static void hello_static(string s) {cout << s << endl;}};int main() {function<void(string)> func1 = &StaticClass1::hello_static;func1("hello world"); //func1.operator()(string) ==> 调用void hello_static(string)return 0;}
模板类静态成员函数:
template<typename T>class StaticClass2 {public:static void hello_static(T out) {cout << out << endl;}};int main() {function<void(string)> func1 = &StaticClass2<string>::hello_static;func1("static.. hello world"); //func1.operator()(string) ==> 调用void StaticClass2<string>::hello_static(string)return 0;}
普通类成员函数:
class Test {public:void hello(string str) {cout << str << endl;}};int main() {// function<void(Test *, string)> func = &Test::hello;// func(&Test(), "call Test::hello"); //这种第一个参数传递匿名对象的方法在GCC8.4下不可行 在vs2017下可行 不建议使用匿名对象Test test; //定义对象function<void(Test *, string)> func1 = &Test::hello;func1(&test, "call Test::hello"); //func1.operator(Test *, string) ==> 调用void Test::hello(string)return 0;}
模板类成员函数:
template<typename T>class Test2 {public:void hello(T str) {cout << str << endl;}};int main() {Test2<string> test2;function<void(Test2<string> *, string)> func1 = &Test2<string>::hello;func1(&test2, "call template Test::hello"); //func1.operator(Test2 *, string) ==> 调用void Test2<string>::hello(string)return 0;}
function底层原理剖析对function
用法有基本了解后,为了剖析function
底层原理,我们还需知道模板的「特例化」以及「可变参数模板』,这里不再说明,可参考我以下两篇博文,已经对模板特化和可变参数模板进行了解释:
- [ 模板全特化与偏特化的概念 ]
- [ 泛化之美 —— C++11 可变参数模板的妙用 ]
function
是C++11特有的一种比函数指针更灵活的机制,现在如果我们要接收一个hello
函数,形如:void hello(string str) { cout << str << endl; }
该如何实现呢?function
利用了函数对象的手段,结合函数指针去调用小括号运算符重载实现,因此理所应当的实现是这样的,内部有一个函数指针_pfunc
,并且该函数指针在operator()
小括号运算符重载重被调用:
经验总结扩展阅读
- 路由器每天晚上都关掉好不好路由器每天晚上都关掉会怎么样
- 路由器放在墙边还是角落 路由器放在哪里比较好
- 路由器辐射是手机的多少倍 路由器辐射怎么减少
- 2023年9月22日是安机器的黄道吉日吗 2023年农历八月初八宜安机器吗
- 2023年9月22日适合安装机器吗 2023年9月22日安装机器好吗
- 2023年9月23日是安机器吉日吗 2023年农历八月初九安机器吉日
- 2023年9月23日是安装机器吉日吗 2023年9月23日安装机器行吗
- .net core Blazor+自定义日志提供器实现实时日志查看器
- 干粉灭火器如何使用
- c类火灾用什么灭火器