C++11中,callable object 包括传统C函数,C++成员函数,函数对象(实现了()运算符的类的实例),lambda表达式(特殊函数对象)共4种。程序设计,特别是程序库设计时,经常需要涉及到回调,如果针对每种不同的callable object单独进行声明类型,代码将会非常散乱,也不灵活。如下示例:

#include <iostream>
#include <functional>
using namespace std;
// 传统C函数
int c_function(int a, int b)
{
return a + b;
} // 函数对象
class Functor
{
public:
int operator()(int a, int b)
{
return a + b;
}
}; int main(int argc, char** argv)
{
int(*f)(int, int); // 声明函数类型,赋值只能是函数指针
f = c_function;
cout << f(, ) << endl; Functor ff = Functor(); // 声明函数对象类型,赋值只能是函数对象
cout << ff(, ) << endl;
}
幸运的是,C++标准库的头文件里定义了std::function<>模板,此模板可以容纳所有类型的callable object.示例代码如下:
#include <iostream>
#include <functional>
using namespace std; // 传统C函数
int c_function(int a, int b)
{
return a + b;
} // 函数对象
class Functor
{
public:
int operator()(int a, int b)
{
return a + b;
}
}; int main(int argc, char** argv)
{
// 万能可调用对象类型
std::function<int(int, int)> callableObject; // 可以赋值为传统C函数指针
callableObject = c_function;
cout << callableObject(, ) << endl; // 可以赋值为函数对象
Functor functor;
callableObject = functor;
cout << callableObject(, ) << endl; // 可以赋值为lambda表达式(特殊函数对象)
callableObject = [](int a, int b){
return a + b;
};
cout << callableObject(, ) << endl;
}

std::function<>的这种多态能力确实很强,这样可以定义一个回调列表,而列表的元素可接受的可调用物类型并不相同。如下:


#include <iostream>
#include <functional>
#include <list>
using namespace std; // 传统C函数
int c_function(int a, int b)
{
return a + b;
} // 函数对象
class Functor
{
public:
int operator()(int a, int b)
{
return a + b;
}
}; int main(int argc, char** argv)
{
Functor functor;
std::list<std::function<int(int, int)>> callables; callables.push_back(c_function);
callables.push_back(functor);
callables.push_back([](int x, int y)->int{
return x + y;
}); for (const auto& e : callables)
{
cout << e(, ) << endl;
}
}

对于使用C回调机制的程序库来说,C++的std::function<>能兼容传统C函数指针,所以库这一端使用std::function<>代替函数指针,并不会影响旧有客户端程序的编码方式。

C++11中万能的可调用类型声明std::function<...>的更多相关文章

  1. callable object与新增的function相关 C++11中万能的可调用类型声明std::function<...>

    在c++11中,一个callable object(可调用对象)可以是函数指针.lambda表达式.重载()的某类对象.bind包裹的某对象等等,有时需要统一管理一些这几类对象,新增的function ...

  2. C++11新特性应用--实现延时求值(std::function和std::bind)

    说是延时求值,注意还是想搞一搞std::function和std::bind. 之前博客<C++11新特性之std::function>注意是std::function怎样实现回调函数. ...

  3. C++11中的std::function

    看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::fun ...

  4. 【转】C++11中的std::function

    原文地址:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard: ...

  5. C++中的各种可调用对象

    概述 一组执行任务的语句都可以视为一个函数,一个可调用对象.在程序设计的过程中,我们习惯于把那些具有复用性的一组语句抽象为函数,把变化的部分抽象为函数的参数. 函数的使用能够极大的极少代码重复率,提高 ...

  6. C++11中std::function的使用

    class template std::function is a general-purpose polymorphic function wrapper. Instances of std::fu ...

  7. 浅谈C++11中的多线程(一)

    摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 同步互斥原理以及多进程和多线程中实现同步互斥的两种方法 Qt中的多线程应用 c++ ...

  8. 一起学习c++11——c++11中的新增的容器

    c++11新增的容器1:array array最早是在boost中出现:http://www.boost.org/doc/libs/1_61_0/doc/html/array.html 当时的初衷是希 ...

  9. Effective Modern C++翻译(6)-条款5:auto比显示的类型声明要更好

        在概念上说,auto关键字和它看起来一样简单,但是事实上,它要更微妙一些的.使用auto会让你在声明变量时省略掉类型,同时也会防止了手动类型声明带来的正确性和性能上的困扰:虽然按照语言预先定义 ...

随机推荐

  1. JAVAEE——宜立方商城06:Redis安装、数据类型和持久化方案、Redis集群分析与搭建、实现缓存和同步

    1. 学习计划 1.首页轮播图展示 2.Redis服务器搭建 3.向业务逻辑中添加缓存. 4.使用redis做缓存 5.缓存同步. 2. 首页轮播图动态展示 2.1. 功能分析 根据分类id查询内容列 ...

  2. CentOS7启动流程

    同样我也找了一张CentOS7的启动流程图. 第一步.硬件启动阶段 这一步和CentOS6差不多,详细请看CentOS6启动流程(含详细流程图) 第二步.GRUB2引导阶段 从这一步开始,CentOS ...

  3. Android Actionbar Tab 导航模式

    Android Actionbar Tab 下图中,红色矩形圈起来的就是我们 ActionBar Tab,下面我们将一步一步的实现下图中的效果. 初次尝试 package com.example.it ...

  4. [ 原创 ]学习笔记-做一个Android音乐播放器是遇到的一些困难

    最近再做一个安卓的音乐播放器,是实验室里学长派的任务,我是在eclipse上进行开发的,由于没有android的基础,所以做起来困难重重. 首先是布局上的困难 1.layout里的控件属性不熟悉 2. ...

  5. luoguP4492 [HAOI2018]苹果树 组合计数 + dp

    首先,每个二叉树对应着唯一的中序遍历,并且每个二叉树的概率是相同的 这十分的有用 考虑\(dp\)求解 令\(f_i\)表示\(i\)个节点的子树,根的深度为\(1\)时,所有点的期望深度之和(乘\( ...

  6. POJ 2891 Strange Way to Express Integers 中国剩余定理 数论 exgcd

    http://poj.org/problem?id=2891 题意就是孙子算经里那个定理的基础描述不过换了数字和约束条件的个数…… https://blog.csdn.net/HownoneHe/ar ...

  7. Codeforces Round #298 (Div. 2) B. Covered Path 物理题/暴力枚举

    B. Covered Path Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/534/probl ...

  8. oracle备份恢复学习

    备份和恢复是常遇到的操作,逻辑备份和物理备份.物理备份又分为冷备份和热备份. 一.逻辑备份,恢复 是指使用exp命令,简单易行,不影响正常的数据库操作.exp   用户名/密码   file=/hom ...

  9. Unity消息

    GameObject关于Message带有三种方法, gameObject.SendMessageUpwards ("test1",4);gameObject.SendMessag ...

  10. Linux- systemd

    systemd被设计用来改进sysvinit的缺点,它和ubuntu的upstart是竞争对手,预计会取代它们.systemd的很多概念来源于苹果的launchd.创始人Lennart是redhat员 ...