文章目录
前言
Java8在Java中通过lambda
表达式、Stream API
引入了函数式编程,那么C++中是否也支持函数式编程呢?答案是肯定的。目前关于C++进行函数式编程的语法探究的相关博客、文章并不多,本篇博客的目的就是阐述利用C++进行函数式编程的几种方法。
为了避免本博客篇幅过大,本博客中只涉及C++函数式编程的语法,不对函数式编程的相关思想和关键概念进行详细阐述,但本博客的最后会给出笔者认为比较好的关于函数式编程的相关参考书籍。如有问题或发现本博客中涉及的bug可以在评论区中提出,谢谢!
阅读完本博客你将会理解和掌握:
- 函数式编程简化代码、复用已有函数、降低编码复杂度的优点
- 函数指针的声明和使用方法
lambda
表达式的形式和用法- 利用函数指针和
lambda
表达式实现C++的函数式编程 - 利用
fuction<T>
模板的声明和用法,并用fuction<T>
模板替代函数指针 functional
头文件中的函数对象和用法- 利用函数式编程对已有代码进行重构
一个简单的编程问题
我想大家在刚刚开始接触编程的时候应该都遇到过这样一个简单的编程问题:
给出3个int
型整数a
、b
、c
,当:
c
为0
时,求出a+b
;c
为1
时,求出a-b
;c
为2
时,求出a*b
;c
为3
时,求出a/b
;
看到这个问题,你会想到怎么实现呢?如果有了想法快去自己实现一下呀(~ ̄▽ ̄)~
我们的第一想法(好吧,只是我的第一想法)应该是用一个map
将c
值和对应的计算方式建立映射关系,显然这个方法目前不可行,因为C++中不支持定义“函数类型”。我们只能退而求其次,使用if-else
语句或者switch-case-break
语句来完成该程序,代码清单1如下:
//代码清单1
#include<iostream>
using namespace std;
int Plus(int a,int b){
//加法
return a+b;
}
int Minus(int a,int b){
//减法
return a-b;
}
int Multiplies(int a,int b){
//乘法
return a*b;
}
int Divides(int a,int b){
//除法
return a/b;
}
int main(){
int a,b,c;
cin>>a>>b>>c;
if(c==0)
cout<<Plus(a,b)<<endl;
else if(c==1)
cout<<Minus(a,b)<<endl;
else if(c==2)
cout<<Multiplies(a,b)<<endl;
else if(c==3)
cout<<Divides(a,b)<<endl;
return 0;
}
显然这样的代码过于臃肿,不够简洁,如果我们可以用map
将c
值和对应的计算方式建立起映射关系,输入c
,直接调用对应的函数,代码会简洁很多,那么我们有什么办法去实现这样的map
吗?(当然有!不然我写这篇博客干啥︿( ̄︶ ̄)︿)
函数指针
C++中没有函数类型
,但是有函数指针
的概念,函数指针指向的是函数而非对象。和其他指针一样,函数指针也具有类型,其类型由指向函数的形参类型和返回类型共同决定。函数指针声明方式是函数返回类型 (*函数指针名) (形参类型列表)
,我们可以按照下面的声明方式声明一个函数指针:
//定义指向包含两个int形参,返回类型为int的函数的函数指针
int (*f)(int,int)=nullptr;//当前该函数指针没有指向任何一个函数
当我们把函数名作为一个值使用时,该函数名自动转换成指针,例如,我们可以这样让f
指针指向我们上一个程序中定义的Plus
函数(注意函数指针与函数的类型必须匹配):
f=Plus;//f指向名为Plus的函数
f=&Plus;//等价的赋值语句,取地址符是可选的
我们可以直接使用函数指针调用一个函数,无须解引用:
int t1=Plus(1,2);//调用Plus函数
int t2=f(1,2);//等价的调用语句
虽然我们不能将多个函数存放到一个数组中,但我们可以将多个函数指针存放在一个数组中,语法是函数返回类型 (*函数指针名[数组维度]) (形参类型列表)
,我们可以按照下面的声明方式声明一个4维的函数指针数组`:
int(*v[4])(int,int);
如何使用标准库中的容器,例如vector
、map
,可以按照下面的声明方式声明一个存放函数指针类型的vector
以及存放int->函数指针
键值对的map
:
vector<int(*)(int,int)>v;
map<int,int(*)(int,int)>m;
哇,好复杂的声明,难道我需要定义函数指针的地方,都要这么声明吗?当然不是,我们可以利用C++中的类型别名机制using
来简化声明:
using pf=int(*)(int,int);//pf是该函数指针类型的一个别名
vector<pf>v;//存放函数指针的vector
map<int,pf>m;//存放`int->函数指针`键值对的`map`
pf f[4];//函数指针数组
因此我们可以利用下面的代码清单2解决刚刚提出的加、减、乘、除的编程问题:
//代码清单2
#include<iostream>
#include<map>
using namespace std;
int Plus(int a,int b){
//加法
return a+b;
}
int Minus(int a,int b){
//减法
return a-b;
}
int Multiplies(int a,int b){