声明函数指针

#include<iostream>
using namespace std;
double a(double aa) { return aa; }
int main() {int aa = 9;
a(1.0); double(*fn)(double) = a;;
cout << a(1.0)<<endl;
cout << fn(1.0) << endl;
cout << fn << endl;
cout << &fn << endl;
cout << *fn << endl; }

  结果:

1
1
00821488
00F3FB70
00821488

回调函数

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
void a(int t) { cout << t << endl; }
void aa(int t) { cout << t*t << endl; }
void callback(void(*fn)(int t),int g) { fn(g); }  //映射函数
int main() {
callback(a, 9);
callback(aa,9); }

  结果

9
81

  

回调函数还没懂应用在哪。

回调函数的限制

  向回调函数中所传递的信息超过了映射函数所能提供的参数。

解决

  函数指针在它们的效用中被限制,因为它们无法将函数与用户提供的数据一起提供。所以需要一种策略:它将回调函数与用户提供的数据封装成一个单独的单元。即函数类(function class)(通过重载operateor()将对象本身作为方法)。这些类的实例称为函数对象(function object)或函子(functor)。

函数对象的简单例子

  例如,函数对其参数值加1:

int add1(int x)
{return x+1;}

  现在改需求了,给定一个整型常量k,对参数值加k。

int addk(int x)
{return x+k;}

  k可为任意整数。你不可能实现与k相同数目的函数。你需要创建一个封装两个构件的函数类:一个变量记录k的值,另一个重载operator(),以便给操作符向其参数增加存储的k值。示例

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
class AddFunction {
public:
AddFunction(int k) { this->k = k; }
int operator()(int x) { return x + k; }
private:
int k;
};
int main() {
AddFunction add1 = AddFunction(1);
AddFunction add17 = AddFunction(17);
cout << add1(100) << endl;
cout << add17(25) << endl;
}

  结果

101
42

  

向映射函数传递函数对象

  使用函数对象的策略可以解决映射函数向回调函数传递额外信息的问题。

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
class AddFunction {
public:
AddFunction(int k) { this->k = k; }
int operator()(int x) { return x + k; }
private:
int k;
};
void callback(AddFunction a, int g) { cout << a(g) << endl; }
int main() {
AddFunction aa(8);
callback(aa,9);
}

  结果

17

  

编写以函数作为参数的函数

  1、函数指针

void callback(void(*fn)(int t),int g) { fn(g); }

  2、函数对象

c++通过使用模板函数来实现任何以函数对象作为参数的函数的方式来解决这个问题。原型如下

template <typename FunctionClass>
void callback(FunctionClass a, int g)

  示例

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
class AddFunction {
public:
AddFunction(int k) { this->k = k; }
int operator()(int x) { return x + k; }
private:
int k;
};
template <typename FunctionClass>
void callback(FunctionClass a, int g) { cout << a(g) << endl; }
int main() {
AddFunction aa(8);
callback(aa,9);
}

  传递给callback的值可以是任何类型。当编译器试图展开callback模板函数时,如果该类型不能重载函数调用操作符以至于不能获得期望的参数,那么编译器就会报错。

c++程序设计基础、编程抽象与算法策略

声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略的更多相关文章

  1. typedef void(*Fun) (void)是什么意思 函数指针(回调函数) 和函数对象总结

    https://blog.csdn.net/FreeApe/article/details/49124043 bool (*pf)(const string &,const string &a ...

  2. C语言笔记 08_函数指针&回调函数&字符串&结构体&位域

    函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...

  3. [Reprint]C++普通函数指针与成员函数指针实例解析

    这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下   C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...

  4. C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)

    //多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...

  5. qsort中的函数指针,及函数解释

    函数指针有何用 函数指针的应用场景比较多,以库函数qsort排序函数为例,它的原型如下: void qsort(void *base,size_t nmemb,size_t size , int(*c ...

  6. selector函数指针回调机制

    selector可以叫做选择器,其实指的就是对象的方法,也可以理解为C语言里面的函数指针,在面向对象里面的对应概念. [self performSelector:@selector(Hidden) w ...

  7. 从成员函数指针生成可调用对象:function<>、mem_fn()和bind()

    我们知道,普通函数指针是一个可调用对象,但是成员函数指针不是可调用对象.因此,如果我们想在一个保存string的vector中找到第一个空string,不能这样写: vector<string& ...

  8. C++学习之普通函数指针与成员函数指针

    函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般函数的函数指针使用的比较多,而对指向类成员函数的函数指针则比较陌生.我最近也被问到了这方面的问题,心中 ...

  9. c++11 符号修饰与函数签名、函数指针、匿名函数、仿函数、std::function与std::bind

    一.符号修饰与函数签名 1.符号修饰 编译器将c++源代码编译成目标文件时,用函数签名的信息对函数名进行改编,形成修饰名.GCC的C++符号修饰方法如下: 1)所有符号都以_z开头 2)名字空间的名字 ...

随机推荐

  1. php代码中临时开启错误调试

    对php.ini 中参数的设置 也可用在php代码中完成. 调用:调用ini_set()函数 //开启php.ini中的display_errors指令 ini_set('display_errors ...

  2. kafka集群配置和java编写生产者消费者操作例子

    kafka 安装 修改配置文件 java操作kafka kafka kafka的操作相对来说简单很多 安装 下载kafka http://kafka.apache.org/downloads tar ...

  3. 第十三章 Spring消息(待续)

    ···············

  4. fiddler代理hosts配置

    1 需求背景 fidder开启后,C:\Windows\System32\drivers\etc\hosts配置失效问题:fiddler本身代理hosts配置表,修改后,可以省去在手机等代理使用者的系 ...

  5. Vulkan Tutorial 03 理解Instance

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Creating an instance 与Vulkan打交道,通常的步骤是创建一个 ...

  6. spring不能注入静态变量的原因

    静态方法是属于类(class)的,普通方法才是属于实体对象(也就是New出来的对象)的,spring注入是在容器中实例化对象,所以不能使用静态方法. @Autowired private static ...

  7. C# 读取文件中的sql语句 创建数据库以及表结构

    大概思路是: 读取文件 根据文件中行内容为GO 作为分割  一条条放到list中 然后在程序中逐条执行sql语句; 值得一提的是 创建数据库的语句是不允许放到程序事务中执行的 所以目前我是分了两个文本 ...

  8. lunix tomcat重启脚步

    [wlcf@iZbp12oby5qekkz14dlokeZ ~]$ cat restart_tomcat #!/bin/shif [ $# != 1 ] ; then echo "USAGE ...

  9. 118. Pascal's Triangle杨辉三角形(全部/一行)

    [抄题]: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5 ...

  10. Android NDK打印log到logcat的方法

    头文件 : <android/log.h> 函数: __android_log_print(ANDROID_LOG_XXX,LOG_TAG,content) 第一个参数是Log级别,比如: ...