文档章节

全局函数指针作为模板参数

zhangyujsj
 zhangyujsj
发布于 2015/08/22 17:49
字数 1019
阅读 188
收藏 2
  • 同样,函数指针型模板参数的意义在于:在变与不变之间取得最优实现。通常函数指针的作用是实现回调(callback),即由调用方将所需要操 作包装成某个函数f0,并将指向此函数的指针&f0作为参数传递给函数f1。函数f1在运行时回调所指函数f0,从而实现调用方所期待操作。f0 就是一个回调函数。将回调函数指针作为被调用函数的参数时,实现的是动态回调,只有在运行时才能确定是回调哪个函数。如果并不需要动态回调,只为方便,在 已有算法框架中嵌入所需操作,则动态回调就略显牛刀杀鸡。此时,将回调函数指针从函数参数移到模板参数,就很容易实现“静态回调”。

    注意 之所以在“静态回调”上加引号,是因为其并不能算做严格的“回调”。回调函数指针是在编译时给定,在模板实例中,就相当于将原本用指针进行回调的地方用所给函数代替,成为完全普通的函数调用。这样也节省了一点点读取指针值确定函数入口的额外运行开销。

    例3.1虽然看起来有些古怪,却演示了函数指针型模板参数的用法。假设对某一数组,需要先依次打印数组元素,依次将元素加1,依次打印,依次将元素减1,再依次打印。

    之所以强调“依次”,是因为对于数组及其他任何序列来说,“依次”操作是一种最常见的需求。但很遗憾,无论C或者C++,都未将“依次”作为内建支 持。每次都用for循环语句来遍历数组固然可行,却会使代码看起来冗长。更好的做法是将“依次”抽象成可复用代码,比如一个foreach函数,再将对数 组元素所做操作包装成一个回调函数,并将其指针传入foreach函数即可。当操作有限且已知时,显然应该将函数指针从foreach函数参数移至模板参 数实现“静态回调”。了解用意后,就不难理解例3.1的代码了。

    例3.1
    #include <iostream>

    // 定义一个foreach函数模板,对数组的每一个元素进行某种操作
    // 具体操作由模板的函数指针参数指定
    template<typename T, void (*f)(T &v)>
    void foreach(T array[], unsigned size)
    {
        for (unsigned i = 0; i < size; ++i) f(array[i]);
    }

    // 三个函数模板用来定义对数组元素的操作
    template<typename T>
    void inc(T &v) {++v;}

    template<typename T>
    void dec(T &v) {--v;}

    template<typename T>
    void print(T &v) {std::cout << ' ' << v;}

    int main()
    {
        int array[] = {1, 2, 3, 4, 5, 6, 7, 8};

        using namespace std;
        foreach<int, print<int> >(array, 8);
        cout << endl;

        foreach<int, inc<int> >(array, 8);
        foreach<int, print<int> >(array, 8);
        cout << endl;

        foreach<int, dec<int> >(array, 8);
        foreach<int, print<int> >(array, 8);
        cout << endl;

        return 0;
    }

    例3.1中,foreach定义为一个函数模板,其第二个模板参数是一个函数指针。由于模板参数必须在编译时给定,所以这个foreach函数实现 了“静态回调”。另有一个值得注意的是,第二个模板参数void(*f)(T*v)的定义中用到第一个模板参数T。这是合法的,在模板参数列表中,所声明 模板参数可立即用于定义随后的模板参数。在本例中,void (*f)(T*v)约束指针型模板参数f所指函数只能接受与前一模板参数类型相同的指针参数,随后所定义的三个函数模板都是要对数据元素进行的操作,分别 是对元素值加1、减1以及打印。在main函数中则调用foreach函数模板,静态绑定对数组每个元素分别加1、减1以及打印。


本文转载自:http://book.2cto.com/201306/25264.html

共有 人打赏支持
zhangyujsj
粉丝 23
博文 358
码字总数 224241
作品 0
广州
C++ 模板(一)

模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。   模板是一种对类型进行参数化的工具...

种地瓜
2016/04/06
22
0
10-C++远征之模板篇-学习笔记

C++远征之模板篇 将会学到的内容: 模板函数 & 模板类 -> 标准模板类 友元函数 & 友元类 静态数据成员 & 静态成员函数 运算符重载: 一切皆有可能 友元函数 函数定义分类: 友元全局函数 例子:...

天涯明月笙
07/24
0
0
[备忘]《C++入门经典》各章小节

《C++入门经典》(即英文版“Beginning C++ The Complete Language”的中译版) 各章小节 第1章 基本概念 ·C++中的程序至少包含一个main()函数。 ·函数的可执行部分由包含在一对花括号中的...

leeoo
2011/12/24
0
0
c++11特性与cocos2d-x 3.0之std::bind与std::function

原文地址:http://www.cnblogs.com/slysky/p/3822640.html 作者:阳光下的蒲公英 c++11特性与cocos2d-x 3.0之std::bind与std::function 昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 ...

智捷课堂
2015/08/21
0
0
语法基础——C++语法基础

前言 最近发现要学习C++来开发NDK,不得不把基础的东西记录下来,否则学的太多会混淆,废话不多说,开始记录我的C++学习之旅吧 HelloWord 导库 命名空间 输出函数 命名空间 1、命名空间属性访...

qq_30379689
2017/08/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

cacti监控安装

cacti是用PHP实现的一个软件,它用snmp服务获取数据,然后用rrdtool存储和更新数据,并生成图表展示。比较适合用于交换机、路由器的网络监控,插件众多,可图示化显示网络状况。 cacti官方推...

hiwill
25分钟前
1
0
shell特殊符号、cut、sort、uniq、wc、tee、tr、split命令

10月15日任务 8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下 cut 命令 cut作用:截取字符串 用法如下:cat /etc/passwd |head -2 |cut -d ...

hhpuppy
54分钟前
1
0
Springboot实现filter拦截token验证和跨域

背景 web验证授权合法的一般分为下面几种 1使用session作为验证合法用户访问的验证方式 使用自己实现的token 使用OCA标准 在使用API接口授权验证时,token是自定义的方式实现起来不需要引入其...

funnymin
今天
3
0
linux使用ntfs-3g操作ntfs格式硬盘

Linux内核目前只支持对微软NTFS文件系统的读取。 NTFS-3G 是微软 NTFS 文件系统的一个开源实现,同时支持读和写。NTFS-3G 开发者使用 FUSE 文件系统来辅助开发,同时对可移植性有益。 安装 ...

linuxprobe16
今天
2
0
kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部